I am pretty new to C#. I am a Borland c++ developer and is used to "newing" and "deleting" objects programmatically.

I understand that with C# the garbage collector is responsible for the deleting of objects.

It seems though that I have a memory leak. I am developing a SQLServerDBInterface class (which I can easily use / include in other future projects). What I notice is that when I call my custom DBConnect function the memory (in task manager for this C# process) increases with a couple of bytes everytime.

Could you please have a look at this code and tell me if I should me deleting the object isntance myself?

Thanks in advance.

This is the code in my interface class

class SqlServerDatabaseInterface
    {
        private const int SI_SUCCESS = 0;
        private const int SI_EXCEPTION = -1000;
        
        SqlConnection g_DbConnection = new SqlConnection();
        SqlCommand g_SqlCommand = new SqlCommand();
        String g_S_AdditionalInformation = "";

        //---------------------------------------------------------------

        public int ConnectToDB()
        {            
            try
            {
                g_DbConnection.Close();

                g_DbConnection.ConnectionString = @"user id=sa;" +
                           "password=password;server=mssqlserver2008;" +
                           "Trusted_Connection=yes;" +
                           "database=Test; " +
                           "connection timeout=30";

                g_DbConnection.Open();
            }
            catch(Exception e)
            {
                g_S_AdditionalInformation = e.Message;
                return SI_EXCEPTION;
            }

            return SI_SUCCESS;
        }

this is the code in my test app that calls the DBinterface class

public partial class frmMain : Form
    {
        SqlServerDatabaseInterface l_SqlServerDatabaseInterface = null;

     public frmMain()
        {
            InitializeComponent();
            l_SqlServerDatabaseInterface = new SqlServerDatabaseInterface();
        }

        //------------------------------------------------------------------

       private void button1_Click(object sender, EventArgs e)
        {
            int l_i_ReturnCode = 0;

            l_i_ReturnCode = l_SqlServerDatabaseInterface.ConnectToDB();

            if (l_i_ReturnCode < 0)
            {
                MessageBox.Show("An error occurred: " +  l_SqlServerDatabaseInterface.GetLastReturnMessage(l_i_ReturnCode), "An error occurred", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

    }

Recommended Answers

All 6 Replies

If your not using the unsafe keyword, I doubt you have a memory leak or a memory leak that you cam fix(i.e. It may be a problem with the database api).

Note: I wouldn't base memory leaks solely on the task manager's memory indicator since C#'s garage collector isn't consistent in its duties.

You shouldn't close and reopen the connection each time. You should check if it is open and if it isn't, open it. Also, database connections do use unmanaged resources (anything dealing with the system software does) and will need to have the Dispose() method called on it.

Calling GC.Collect() will force the garbage collector to 'catch up' with memory freeing. And like Momerath said, calling Dispose() on a class that implements the IDisposable interface will tell the GC to free up the memory associated with the reference. I don't think this is required as he said though, I am pretty sure that the GC will eventually get around to freeing up the resources.

However, if you are referencing an unmanaged object written in C++ or another unmanaged environment then you may want to investigate that library's code for memory leaks. It will prove difficult if not impossible to try and fix this kind of issue from within C#.

Thank you so much gentlemen! All the posts helped a lot. I do now check if the connection is open, although this did not 'solve' the 'memory leak', but I agree, it is good practice.

I do call GC.Collect() after calling any of my DBInterface functions and now the memory usage in task manager remains static. Thank you!

So now my final question on this topic ( for now :) ).

Almost all of the functionality / classes are based on the System namespace, does this mean I have to call dispose or collect myself after every call OR how would I know on which classes I should call dispose or collect i.e. how do I find out which classes implements the IDisposable interface (do I check the help file on each class) or do I just accept that the garbage collector will catch up eventually?

Generally if the class has something to do with hardware (files on the drive, the screen, databases, etc.) it has an unmanaged component to it. The GC will not clean those up for you (the system will, eventually, after your program stops running). The easiest way to know is use intellisence. When you type your variables name and hit the . (<- thats a period over there, I know it's hard to see) you should get a pop-up box of all the methods available. If Dispose() is one of them, then you should Dispose of it.

One way to dispose of objects is the alternate use of the using statement. For example:

using (SqlCommand command = new SqlCommand("Select * from SomeTable") {
    ... rest of code here
}

This will automatically call Dispose() at the end of the statement block. It's the exact same as writing

SqlCommand command = new SqlCommand("Select * from SomeTable");
try {
    ... rest of code here
} finally {
    if (command != null) {
        command.Dispose();
    }
}

The compiler just handles all the extra code for you. This is used commonly with files, since you tend to open them, read what you need, then close them. By using the using syntax, you ensure that system resources are released.

Thank you all!! really appreciate it!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.