| Bug #50944 | Memory leak in C API | ||
|---|---|---|---|
| Submitted: | 5 Feb 2010 14:15 | Modified: | 6 Feb 2010 6:04 |
| Reporter: | Scott Johnson | Email Updates: | |
| Status: | Not a Bug | Impact on me: | |
| Category: | MySQL Server: C API (client library) | Severity: | S2 (Serious) |
| Version: | mysql-server-5.1.42-7.fc12.i686, 5.1 | OS: | Linux (Fedora Core 12) |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | memory leak valgrind c api | ||
[5 Feb 2010 18:48]
Sveta Smirnova
Thank you for the report. Verified as described. Shorter test to repeat: $cat bug50944.c #include <stdio.h> #include <mysql.h> int main( void ) { MYSQL conn; const char *server = "win2003-x86"; const char *user = "root"; const char *password = ""; const char *database = "sbtest"; mysql_init(&conn); if (!mysql_real_connect(&conn, server, user, password, database, 33051, NULL, 0)) { return 1; } mysql_close(&conn); return 0; } Valgrind output: $valgrind --leak-check=full ./bug50944 ==13378== Memcheck, a memory error detector ==13378== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==13378== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==13378== Command: ./bug50944 ==13378== ==13378== ==13378== HEAP SUMMARY: ==13378== in use at exit: 44,728 bytes in 12 blocks ==13378== total heap usage: 77 allocs, 65 frees, 94,545 bytes allocated ==13378== ==13378== 4,060 bytes in 1 blocks are possibly lost in loss record 4 of 7 ==13378== at 0x4A05E13: malloc (vg_replace_malloc.c:195) ==13378== by 0x4C89922: my_once_alloc (my_once.c:61) ==13378== by 0x4C8A6DC: add_collation (charset.c:229) ==13378== by 0x4C99964: cs_leave (ctype.c:205) ==13378== by 0x4CB4EC0: my_xml_leave (xml.c:252) ==13378== by 0x4CB535F: my_xml_parse (xml.c:374) ==13378== by 0x4C99EA3: my_parse_charset_xml (ctype.c:306) ==13378== by 0x4C8AC48: my_read_charset_file (charset.c:346) ==13378== by 0x4C8AF2E: init_available_charsets (charset.c:426) ==13378== by 0x4C8B477: get_charset_by_csname (charset.c:562) ==13378== by 0x4CBC462: mysql_init_character_set (client.c:1805) ==13378== by 0x4CBD5FA: mysql_real_connect (client.c:2222) ==13378== ==13378== 4,060 bytes in 1 blocks are possibly lost in loss record 5 of 7 ==13378== at 0x4A05E13: malloc (vg_replace_malloc.c:195) ==13378== by 0x4C89922: my_once_alloc (my_once.c:61) ==13378== by 0x4C89A34: my_once_strdup (my_once.c:86) ==13378== by 0x4C8A330: cs_copy_data (charset.c:146) ==13378== by 0x4C8A7FF: add_collation (charset.c:245) ==13378== by 0x4C99964: cs_leave (ctype.c:205) ==13378== by 0x4CB4EC0: my_xml_leave (xml.c:252) ==13378== by 0x4CB535F: my_xml_parse (xml.c:374) ==13378== by 0x4C99EA3: my_parse_charset_xml (ctype.c:306) ==13378== by 0x4C8AC48: my_read_charset_file (charset.c:346) ==13378== by 0x4C8AF2E: init_available_charsets (charset.c:426) ==13378== by 0x4C8B477: get_charset_by_csname (charset.c:562) ==13378== ==13378== 12,180 bytes in 3 blocks are possibly lost in loss record 6 of 7 ==13378== at 0x4A05E13: malloc (vg_replace_malloc.c:195) ==13378== by 0x4C89922: my_once_alloc (my_once.c:61) ==13378== by 0x4C89F82: init_state_maps (charset.c:65) ==13378== by 0x4C8AECF: init_available_charsets (charset.c:420) ==13378== by 0x4C8B477: get_charset_by_==13378== by 0x4C89922: my_once_alloc (my_once.c:61) ==13378== by 0x4C89F82: init_state_maps (charset.c:65) ==13378== by 0x4C8AECF: init_available_charsets (charset.c:420) ==13378== by 0x4C8B477: get_charset_by_csname (charset.c:562) ==13378== by 0x4CBC462: mysql_init_character_set (client.c:1805) ==13378== by 0x4CBD5FA: mysql_real_connect (client.c:2222) ==13378== by 0x40086A: main (bug50944.c:16) ==13378== ==13378== 16,240 bytes in 4 blocks are possibly lost in loss record 7 of 7 ==13378== at 0x4A05E13: malloc (vg_replace_malloc.c:195) ==13378== by 0x4C89922: my_once_alloc (my_once.c:61) ==13378== by 0x4C89F51: init_state_maps (charset.c:62) ==13378== by 0x4C8AECF: init_available_charsets (charset.c:420) ==13378== by 0x4C8B477: get_charset_by_csname (charset.c:562) ==13378== by 0x4CBC462: mysql_init_character_set (client.c:1805) ==13378== by 0x4CBD5FA: mysql_real_connect (client.c:2222) ==13378== by 0x40086A: main (bug50944.c:16) ==13378== ==13378== LEAK SUMMARY: ==13378== definitely lost: 0 bytes in 0 blocks ==13378== indirectly lost: 0 bytes in 0 blocks ==13378== possibly lost: 36,540 bytes in 9 blocks ==13378== still reachable: 8,188 bytes in 3 blocks ==13378== suppressed: 0 bytes in 0 blocks ==13378== Reachable blocks (those to which a pointer was found) are not shown. ==13378== To see them, rerun with: --leak-check=full --show-reachable=yes ==13378== ==13378== For counts of detected and suppressed errors, rerun with: -v ==13378== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 8 from 8)
[6 Feb 2010 4:05]
Georg Richter
Hi, this looks like a duplicate of #45002. Example code doesn't call mysql_library_end().
[6 Feb 2010 6:04]
Sveta Smirnova
Georg, thank you for the update. You are right: duplicate of bug #45002 and not a bug.

Description: I've been playing around with this for a while. I've read other bug reports with similar issues but I'm almost convinced that it's a MySQL issue now. Take this code for example: int Main( void ) { char szQuery[80]; MYSQL *conn = NULL; MYSQL_RES *res = NULL; MYSQL_ROW row; const char *server = "10.1.1.109"; const char *user = "testdb"; const char *password = "1234567890"; const char *database = "dbtest"; sprintf( szQuery, "select * from tblControl LIMIT 1" ); if( mysql_library_init( 0, NULL, NULL) ) { syslog( LOG_INFO, "MySQL: library is unable to initialize."); exit(1); } mysql_init(conn); if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { syslog(LOG_INFO, "MySQL: %s", mysql_error(conn)); exit(1); } syslog( LOG_INFO, szQuery ); if( mysql_query( conn, "select * from tblControl LIMIT 1") ) syslog( LOG_INFO, "MySQL: SQL Query Error: %d", mysql_error(conn) ); res = mysql_store_result( conn ); row = mysql_fetch_row(res); printf("%s \n", row[0]); mysql_free_result(res); syslog( LOG_INFO, "Closing mysql" ); mysql_close(conn); return TRUE; } Valgrind reports that I've lost a block of memory. ==30989== LEAK SUMMARY: ==30989== definitely lost: 964 bytes in 1 blocks ==30989== indirectly lost: 0 bytes in 0 blocks ==30989== possibly lost: 0 bytes in 0 blocks ==30989== still reachable: 16 bytes in 1 blocks I've played around with this a lot and one of the things I did was change the variable type of MySQL *conn; to MySQL conn; ==30989== LEAK SUMMARY: ==30989== definitely lost: 0 bytes in 0 blocks ==30989== indirectly lost: 0 bytes in 0 blocks ==30989== possibly lost: 53,144 bytes in 13 blocks ==30989== still reachable: 8,192 bytes in 3 blocks From reading the docs on mysql_init; it's supposed to create assign an object when the variable is set to NULL so I should not need to use a new() on it. I also set up a mysql_free_result on what I get back. Oh, also, I don't think it has to do with the result. If I take off the query and just leave the mysql initialization portions on I get the leak as well. I think it's not freeing up the connection object properly. Then replaced the pointers in the function to &conn. It works better but I still get possible lost memory. This would be all fine and dandy and I wouldn't worry too much about it if the program just ran then quit. This function is part of a Daemon that will be running 24x7x365. I don't want to worry about shutting down and restarting the process. How to repeat: See above