Reputation: 11768
I am writing a daemon in C++, it has a simple task of inserting some events into a mysql database.
When I ran the top command I saw that the processe's memory needs increase, I thought I had a memory leak and I started using Valgrind
I ran valgrind as this:
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./my_app
I get the following report:
==17045== 128 bytes in 1 blocks are definitely lost in loss record 6 of 11
==17045== at 0x402A629: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==17045== by 0x40AAB63: my_thread_init (in /usr/lib/i386-linux-gnu/libmysqlclient.so.18.0.0)
==17045== by 0x40AAE43: my_thread_global_init (in /usr/lib/i386-linux-gnu/libmysqlclient.so.18.0.0)
==17045== by 0x40A92D7: my_init (in /usr/lib/i386-linux-gnu/libmysqlclient.so.18.0.0)
==17045== by 0x40863FA: mysql_server_init (in /usr/lib/i386-linux-gnu/libmysqlclient.so.18.0.0)
==17045== by 0x4087B28: mysql_init (in /usr/lib/i386-linux-gnu/libmysqlclient.so.18.0.0)
==17045== by 0x8049890: write_db(std::string, std::string, std::string) (Listener.cpp:76)
==17045== by 0x804A692: SocketListener(void*) (Listener.cpp:182)
==17045== by 0x4052D4B: start_thread (pthread_create.c:308)
==17045== by 0x4582D3D: clone (clone.S:130)
The function write_db is this:
void write_db(std::string userid,std::string zona,std::string eveniment)
{
try
{
MYSQL * connect;
connect = mysql_init(NULL);
connect = mysql_real_connect(connect,"127.0.0.1","myusr","mypwd","mytbl",0,NULL,0);
std::string stmt = "INSERT INTO t_evenimente(placaid,codev,zona,cand) VALUES(\"" + userid + "\"," + eveniment + ",\"" + zona + "\",NOW())";
std::cout << stmt << std::endl;
mysql_query(connect,stmt.c_str());
mysql_close(connect);
std::cout << "Inserat eveniment obiectiv " << userid << std::endl;
}
catch (...)
{
std::cout <<"Exceptie MYSQL" << std::endl;
}
}
Where is the memory leak ? I am using mysql_init and close as the documentation says...Could it be a false positive ?
Upvotes: 1
Views: 911
Reputation: 180927
Since you're using connect
only inside your function, it's easier not to allocate it dynamically and risk a memory leak (most likely the one you're seeing). Also, the MySQL API is a C API and does not throw any exceptions for you to catch, which will simplify what you have now down to something like;
void write_db(std::string userid,std::string zona,std::string eveniment)
{
MYSQL connect;
mysql_init(&connect);
mysql_real_connect(&connect,"127.0.0.1","myusr","mypwd","mytbl",0,NULL,0);
std::string stmt = "INSERT INTO t_evenimente(placaid,codev,zona,cand) VALUES(\"" + userid + "\"," + eveniment + ",\"" + zona + "\",NOW())";
std::cout << stmt << std::endl;
mysql_query(&connect,stmt.c_str());
mysql_close(&connect);
std::cout << "Inserat eveniment obiectiv " << userid << std::endl;
}
Of course, that still leaves out error handling, which you'll need to add back.
Upvotes: 1
Reputation: 1316
mysql_init returns a heap allocated object which needs to be freed by mysql_close. In the case when something in between mysql_init and mysql_close throws an exception, you never call close. Quick fix - add mysql_close to the catch block. Better fix - learn about/use RAII.
As Angew pointed out, it's actually probably more likely you are leaking the connection when you call mysql_real_connect (unless you are seeing your exception text in the log). You could use RAII to avoid this too.
Upvotes: 1