Question

I've been scratching my head over this for the past month now and I still can't figure out what is going on.

The problem is that I have a very serious memory leak on a C++ application running on Windows Server 2008, compiled using Visual Studio 2005. This is a managed project. The application starts at around 5-6MB (according to Task Manager) and starts to exhibit symptoms of failure around the ~200MB mark. I know Task Manager is a crude tool, but given the scale of the leak it seems OK to use.

I've narrowed the problem to MySQL Database interaction. If the application does not interact with the database, no memory is leaked.

All database interactions use mysql++. I've followed the build instructions in the man pages on tangentsoft.net.

We've evaluated the code for thread safety (that is, we ensured that each thread only uses mysqlpp object from that thread and no other) and checked to make sure all destructors are called for any dynamically generated objects created using 'new'.

Looking on the internet I keep seeing various reports from users of the mysqlpp class that indicate there is a leak somewhere. In particular, there was a discussion about how the Win C API would leak when mysqlpp was used:

http://www.phpmarks.com/6-mysql-plus/ffd713579bbb1c3e.htm

This discussion seems to conclude in a fix, however, when I try the fixes in my application it still leaks.

I implemented a version of the application cited in the thread above, but with some of the advice from the man pages added:

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    while (true)
    {
        //Initialise MySQL API
        mysql_library_init(0, NULL, NULL);

        Sleep(50);        
        //Connect to Database.
        mysqlpp::Connection c;        
        c.connect("myDatabase","localhost","username","password");

        Sleep(50);
        //Disconnect from Database
        c.disconnect();

        Sleep(50);
        //Free memory allocated to the heap for this thread
        c.thread_end();

        Sleep(50);
        //Free any memory allocated by MySQL C API
        mysql_library_end();

        Sleep(50);
    }
    return 1;
}

I added the Sleep(50) just to throttle each stage of the loop, so that each function has time to "settle down". I know it probably isn't necessary but at least this way I can eliminate that as a cause.

Nevertheless, this program leaks quite rapidly (~1mb per hour).

I've seen similar questions to mine asked in a few places, with no conclusions made :(

So i'm not alone with this issue. It occurs to me that the mysqlpp class has a reputation for usefulness and so must be quite robust. Given that is the case, I still can't see what i've done wrong. Does anyone have some experience of mysqlpp with Visual Studio 2005 that might shed light on the problem?

Cheers, Adam.

EDIT

I created another example using a pointer, just in case c was being duplicated in the loop:

//LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    mysqlpp::Connection * c;

    while (true)
    {
        mysql_library_init(0, NULL, NULL);

        c = new mysqlpp::Connection;

        Sleep(50);

        c->connect("myDatabase","localhost","username","password");

        Sleep(50);
        c->disconnect();

        Sleep(50);
        c->thread_end();

        Sleep(50);
        mysql_library_end();

        Sleep(50);

        delete c;
        c = NULL;
    }       
    return 1;
}

This also leaks. I then created a control example based on this code, which doesn't leak at all:

//NOT LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    char * ch;

    while (true)
    {
        mysql_library_init(0, NULL, NULL);

        //Allocate 4000 bytes
        ch = new char [4000];

        Sleep(250);

        mysql_library_end();

        delete ch;
        ch = NULL;

    }
return 1;
}

Note that I also left the calls to the MySQL C API here to prove that it isn't the cause of the leak. I then created an example using a pointer but without the calls to connect/ disconnect:

//NOT LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{

    mysqlpp::Connection * c;

    while (true)
    {
        mysql_library_init(0, NULL, NULL);

        c = new mysqlpp::Connection;
        Sleep(250);

        mysql_library_end();

        delete c;
        c = NULL;
    }

return 1;
}

This doesn't leak.

So the difference is just the use of the mysqlpp::connect / disconnect methods. I'll dig into the mysqlpp class itself and try to see whats up.

Cheers, Adam.

EDIT

Here is an example of the leaky code where checks are made.

//LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    mysqlpp::Connection * c;

    while (true)
    {
        mysql_library_init(0, NULL, NULL);

        c = new mysqlpp::Connection;

        Sleep(50);

        if ( c->connect("myDatabase","localhost","username","password") == false )
        {
            cout << "Connection Failure";
            return 0;
        }

        Sleep(50);
        c->disconnect();

        Sleep(50);
        c->thread_end();

        Sleep(50);
        mysql_library_end();

        Sleep(50);

        delete c;
        c = NULL;
    }       
return 1;
}

Cheers, Adam.

No correct solution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top