Background:
MySQL++ ( libsqlplus ) is a pretty nice official C++ styled mysql client 
library wrapper of libmysqlclient. It offers STL-style C++ interface and is 
designed with an effort of generic programming style. It should be a really 
excellent choise if only it had not a MEMORY LEAK problem.
http://www.mysql.com/downloads/api-mysql++.html

Investigation:
As this library is commonly used to develop a CGI C++ application problem is 
not so crytical. CGI process lives just a few seconds and then dies, all 
memory it have been using is deallocated by the system. I've fortunely found 
this bug developing apache mod_rewrite program map application that should 
stay alive all the apache lifetime. It cannot be restarted without httpd 
restart, and if it craches it crashes apache too =(

I use a little subset of mysql++ capabilities 
        - Connection
        - Query ( only Query::store )
        - Result
Memory leak I discovered is located somewhere in Result::operator= and is 
available only after update;
Proof of concept code is supplied. 
It leaks 1 Mb of memory in 10 seconds executing about 12000 updates
I use Intel celeron 333, 2.4.18 linux kernel on late slackware distibution.
MySQL++ 1.7.9 built from source, no __USLC__ conditional defined

Workaround:
Recreating Result object each query elminates this problem.
But we still hope on MySQL++ development team, aint we =?

Links:
Note that I have been using just a little subset of MySQL++, further memory 
leaks may follow. 
mailing.database.myodbc and mailing.database.mysql group has several repots 
about -- have a look at them
( Google->groups search result on 'mysql++ memory leak' )
--
http://groups.google.com.ru/groups?q=mysql%2B%2B+memory+leak&hl=ru&lr=&ie=UTF-8&inlang=ru&selm=a9p6vn%242oci%241%40FreeBSD.csie.NCTU.edu.tw&rnum=3
http://groups.google.com.ru/groups?q=mysql%2B%2B+memory+leak&hl=ru&lr=&ie=UTF-8&inlang=ru&selm=2ed0f107.0203200439.2b4ef27a%40posting.google.com&rnum=2


// -------------------- Proof of concept ---------------------------
#include <iostream>
#include <mysql++>
using namespace std;

#define DBNAME "test"
#define DBHOST "localhost"
#define DBUSER "root"
#define DBPW ""

const string dbname(DBNAME);
const string dbhost(DBHOST);
const string dbuser(DBUSER);
const string dbpw(DBPW);

#define dlog cerr
Connection* con=0;
Result res;

//Result *res=0;

void sql(const char* q)
{
    //    dlog << "[ DB ] Query sent: " << q << endl;
    try {
        Query query = con->query();

        // Use of dynamically allocated and manually cleaned Result
        // will eliminate memory leak
        
        // if(res) delete res;
        // res=new Result();
        // *res=query.store(q);

        // This is another workaround:
        // res.purge() // I soppose this is not called or called incorrectly in 
ResUse::operator=
        // MEMORY LEAK
        res=query.store(q);

    }
    catch(BadQuery &e)
    {
        dlog << "[ DB ] MySQLLow -- BadQuery: " << e.error << endl;    
        throw;
    }
    catch(exception& e)
    {
        dlog << "[ DB ] MySQLLow -- exception: " << e.what() << endl;    
        throw;
    }
    catch(...)
    {
        dlog << "[ DB ] MySQLLow -- exception: ?" << endl;    
        throw;
    }
}

void connect(void)
{
    dlog << "[ DB ] Connecting to database: " << dbname << endl;

    try {
        con=new Connection(use_exceptions);
        con->connect("",dbhost.c_str(),dbuser.c_str(),dbpw.c_str());
        try {
            con->select_db(dbname);
        } catch (BadQuery &er) {
            con->create_db(dbname.c_str());
            con->select_db(dbname.c_str());
        }
    }
    catch(BadQuery &e)
    {
        dlog << "MySQLLow -- BadQuery: " << e.error << endl;
        throw;
    }
    catch(exception& e)
    {
        dlog << "MySQLLow -- exception: " << e.what() << endl;    
        throw;
    }

}

int main(void)
{
    connect();    
    int i=0;
    while(true)
    {
        sql("SELECT * FROM a");

        // comment out this line to eliminate memory leak
        sql("UPDATE a SET i=i+1");
        dlog << '.';
    }
}

// Table creation command: 
// CREATE TABLE a ( i integer);

-- 

Sincerely yours
Peter Kerzum







---------------------------------------------------------------------
Before posting, please check:
   http://www.mysql.com/manual.php   (the manual)
   http://lists.mysql.com/           (the list archive)

To request this thread, e-mail <[EMAIL PROTECTED]>
To unsubscribe, e-mail <[EMAIL PROTECTED]>
Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php

Reply via email to