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