Bug #7619 Memory leak when mysql_init() and mysql_real_connect() [MYSQL C API's] used
Submitted: 2 Jan 2005 16:37 Modified: 16 May 2006 7:26
Reporter: TestUser U Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:3.23.58, 4.1.8, 5.0.2-alpha OS:Linux (Linux 9.0)
Assigned to: Alexander Barkov CPU Architecture:Any

[2 Jan 2005 16:37] TestUser U
Description:
Iam using MySQL C API's to access MYSQL  database.

i compiled a following code which opens a connection and immediately closes a connection with ccmalloc which is memory leak detect software for c,c++.

int main()
{
MYSQL *connection,mysql;
mysql_init(&mysql);
connection=mysql_real_connect(&mysql,host,user,pwd,db,0,0,0);
     if( connection == NULL )
      {
     cout<<sql_error(&mysql);
        exit (1);
      }                                                                                                                             
mysql_close(connection);
return 0;
}

if i use MySQL client library 3.23.58  to execute this code, garbage is 6950 bytes.
if i use MySQL client library 4.1.8 to execute this code , garbage is   26554 bytes.
if i use MySQL client library 5.0.2-alpha to execute this code , garbage is 27326 bytes.

when i execute obj file,ccmalloc (memory leak detect software) shows 6950 bytes garbase in this code for MySQL client library 3.23.58.
Following are the places where memory leak occurs which is showed by  ccmalloc,

58.8% = 4088 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d5b in <main>
|       |       0x0804ba36 in <mysql_real_connect>
|       |       0x08052751 in <get_charset>
|       |       0x08052107 in <init_available_charsets>
|       |       0x08051f2d in <read_charset_index>
|       |      0x08056443 in <my_once_alloc>
|       |-----> 0x08063257 in <malloc>
                          at src/wrapper.c:318

* 14.7% = 1024 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |       0xb74a37de in <???>
|       |`-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

  9.9% = 688 Bytes of garbage allocated in 18 allocations
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |       0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0003 in <???>
|       |       0xb749e49b in <???>
|       |       0xb749ea2a in <???>
|       |       0xb749f0cd in <???>
|       |       0xb749eb23 in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

 8.4% = 582 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |       0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |       0xb749e4cf in <???>
|       |       0xb749e8ac in <???>
|       |       0xb74c0638 in <???>
|       |       0xb75f7b56 in <???>
|       |       0xb74c07a3 in <???>
|       |       0xb74be95c in <???>
|       |       0xb75f7b56 in <???>
|       |       0xb74beaeb in <???>
|       |       0xb75f00d3 in <???>
|       |       0xb75f14df in <???>
|       |       0xb75f4d73 in <???>
|       |       0x08063338 in <calloc>
|       |       at src/wrapper.c:422
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

 3.5% = 242 Bytes of garbage allocated in 15 allocations
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |      0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0003 in <???>
|       |       0xb749e49b in <???>
|       |       0xb749ea2a in <???>
|       |       0xb749f0a5 in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

 2.1% = 144 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |       0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |       0xb749e4cf in <???>
|       |       0xb749e8ac in <???>
|       |       0xb74c0638 in <???>
|       |       0xb75f7b56 in <???>
|       |       0xb74c07a3 in <???>
|       |       0xb74be95c in <???>
|       |       0xb75f7b56 in <???>
|       |       0xb74bf36d in <???>
|       |       0xb75f8a27 in <???>
|       |       0x08063338 in <calloc>
|       |      at src/wrapper.c:422
|       |`-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

0.9% = 64 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d5b in <main>
|       |       0x0804ba36 in <mysql_real_connect>
|       |       0x08052751 in <get_charset>
|       |       0x080520f4 in <init_available_charsets>
|       |       0x08051889 in <init_dynamic_array>
|       |       0x0804eeb6 in <my_malloc>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

 0.4% = 28 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |       0xb749e4cf in <???>
|       |      0xb749e8ac in <???>
|       |       0xb74c0638 in <???>
|       |       0xb75f7b56 in <???>
|       |      0xb74c07a3 in <???>
|       |       0xb74be95c in <???>
|       |      0xb75f7b56 in <???>
|       |      0xb74bed3c in <???>
|       |      0xb75f6bad in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

 0.3% = 23 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |       0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |       0xb749e4cf in <???>
|       |       0xb749e8ac in <???>
|       |       0xb74c0638 in <???>
|       |     0xb75f7b56 in <???>
|       |       0xb74c07a3 in <???>
|       |      0xb74be95c in <???>
|       |     0xb75f7b56 in <???>
|       |     0xb74beaeb in <???>
|       |       0xb75f00d3 in <???>
|       |      0xb75f14df in <???>
|       |      0xb75f4f8e in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318
|
|  0.3% = 23 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |      0x0804af44 in <mysql_init>
|       |      0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |       0xb749e4cf in <???>
|       |    0xb749e8ac in <???>
|       |       0xb74c0638 in <???>
|       |       0xb75f7b56 in <???>
|       |       0xb74c07a3 in <???>
|       |       0xb74be95c in <???>
|       |       0xb75f7b56 in <???>
|       |       0xb74beaeb in <???>
|       |     0xb75f05b3 in <???>
|       |`-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318
|
|  0.2% = 16 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |      0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |      0xb74a39e9 in <???>
|       |     0xb74a0027 in <???>
|       |     0xb749e4cf in <???>
|       |       0xb749e72f in <???>
|       |       0xb748b82c in <???>
|       |`-----> 0x08063257 in <malloc>
|                         at src/wrapper.c:318
|
|  0.2% = 12 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |       0x08049d32 in <main>
|       |       0x0804af44 in <mysql_init>
|       |       0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |      0xb749e4cf in <???>
|       |       0xb749e8f2 in <???>
|       |      0xb749f16c in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318
|
|  0.1% = 8 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |      0x08049d32 in <main>
|       |     0x0804af44 in <mysql_init>
|       |      0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |    0xb74a0003 in <???>
|       |       0xb749e49b in <???>
|       |       0xb749e97e in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318
|
|  0.1% = 8 Bytes of garbage allocated in 1 allocation
|       |
|       |       0xb73c8748 in <???>
|       |      0x08049d32 in <main>
|       |      0x0804af44 in <mysql_init>
|       |     0x0804b057 in <mysql_once_init>
|       |      0xb74a3818 in <???>
|       |       0xb74a39e9 in <???>
|       |       0xb74a0027 in <???>
|       |      0xb749e4cf in <???>
|       |     0xb749e76e in <???>
|       | `-----> 0x08063257 in <malloc>
|                          at src/wrapper.c:318

Please you let  me know how to avoid this Memory Leak.

How to repeat:
if  this bug fixed,you please let me know how it has fixed.

Suggested fix:
mysql_close(MYSQL * connection)   has to free all the memory allocation which are all allocated by connection object.
[8 Jan 2005 21:36] Ivgeni Segal
Found the same problem by using valgrind. In our case we ran libmysql through php.
The cs_info_table is never freed under charset.c
[21 Jun 2005 9:43] Barry Zubel
Verified on Debian, with 4.0.24 client libs and server.
[24 Jul 2005 12:21] Sela Lerer
Got the same problem on WIN XP without using the mysql_init() allocation.

The code:
#include <stdio.h>
#include <windows.h>
#include <mysql.h>

#define CONNECTION_COUNT 4

void printMemStat(void)
{
	MEMORYSTATUS memStat;
	GlobalMemoryStatus(&memStat);
	printf("FREE MEMORY %uK/%uK
(%3.2lf%%)\n",memStat.dwAvailVirtual/1024,memStat.dwTotalVirtual/1024
		,((double)memStat.dwAvailVirtual/(double)memStat.dwTotalVirtual)*100);
	printf("USED MEMORY
%uK\n",(memStat.dwTotalVirtual-memStat.dwAvailVirtual)/1024);
}

int main(int argc, char *argv[])
{
	if(mysql_thread_safe())
	{
		static MYSQL conn[CONNECTION_COUNT];
		int connected[CONNECTION_COUNT]={0};
		int i=0;
		my_init();
		printf("START: ");
		printMemStat();
		for(i=0;i<CONNECTION_COUNT;i++)
		{
			printf("Before connection %d...\n",i);
			printMemStat();
			getchar();
			if(NULL!=mysql_real_connect(&conn[i],"localhost","root","sela90","kevin",3306
,NULL,CLIENT_MULTI_STATEMENTS))
			{
				connected[i]=1;
				printf("Connected %d successfully.\n",i);
				printMemStat();
			}
			else
			{
				fprintf(stderr,"mysql_real_connect() %d error:
%s\n",i,mysql_error(&conn[i]));
			}
		}
		for(i=0;i<CONNECTION_COUNT;i++)
		{
			if(connected[i])
			{
				printf("Before closing connection %d...\n",i);
				printMemStat();
				getchar();
				mysql_close(&conn[i]);
				printf("Closed connection %d.\n",i);
				printMemStat();
			}
		}
		printf("Before mysql_thread_end()....\n");
		getchar();
		mysql_thread_end();
		printf("EXIT: ");
		printMemStat();
		getchar();
	}
	else
	{
		fprintf(stderr,"MySQL client library is not thread safe. Exiting.\n");
		getchar();
	}
	return 0;
}
[23 Sep 2005 7:27] [ name withheld ]
I have similar memory leaks on Debian (Sarge) with 4.1.11 mysql server and client. The problem even appears when no connection is established. This is the minimal C source:

#include <mysql/mysql.h>

    int main()
    {
        MYSQL* mysql = mysql_init(0);

        mysql_close(mysql);

        return 0;
    }

and valgrind --leak-check=full --show-reachable=yes

==21928== Memcheck, a memory error detector for x86-linux.
==21928== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==21928== Using valgrind-2.4.0, a program supervision framework for x86-linux.
==21928== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==21928== For more details, rerun with: -v
==21928==
==21928==
==21928== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 29 from 1)
==21928== malloc/free: in use at exit: 30 bytes in 2 blocks.
==21928== malloc/free: 61 allocs, 59 frees, 6952 bytes allocated.
==21928== For counts of detected errors, rerun with: -v
==21928== searching for pointers to 2 not-freed blocks.
==21928== checked 1093632 bytes.
==21928==
==21928== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2
==21928==    at 0x1B90459D: malloc (vg_replace_malloc.c:130)
==21928==    by 0x1B8E9346: (within /lib/ld-2.3.2.so)
==21928==    by 0x1B8EA5A5: _dl_map_object (in /lib/ld-2.3.2.so)
==21928==    by 0x1B8EEB08: (within /lib/ld-2.3.2.so)
==21928==    by 0x1B8F0015: _dl_catch_error (in /lib/ld-2.3.2.so)
==21928==    by 0x1B8EF580: _dl_map_object_deps (in /lib/ld-2.3.2.so)
==21928==    by 0x1BB2C100: (within /lib/tls/libc-2.3.2.so)
==21928==    by 0x1B8F0015: _dl_catch_error (in /lib/ld-2.3.2.so)
==21928==    by 0x1BB2BED5: _dl_open (in /lib/tls/libc-2.3.2.so)
==21928==    by 0x1BB2DD62: (within /lib/tls/libc-2.3.2.so)
==21928==    by 0x1B8F0015: _dl_catch_error (in /lib/ld-2.3.2.so)
==21928==    by 0x1BB2DBE7: __libc_dlopen_mode (in /lib/tls/libc-2.3.2.so)
==21928==
==21928==
==21928== 26 bytes in 1 blocks are definitely lost in loss record 2 of 2
==21928==    at 0x1B90459D: malloc (vg_replace_malloc.c:130)
==21928==    by 0x1BD74F81: ???
==21928==    by 0x1BD74E4A: ???
==21928==    by 0x1BD46FC1: ???
==21928==    by 0x1BD3E128: ???
==21928==    by 0x1BCDF995: ???
==21928==    by 0x1BCDFB0A: ???
==21928==    by 0x1BCDF1BE: ???
==21928==    by 0x1BCDF46F: ???
==21928==    by 0x1BB11208: getservbyname_r (in /lib/tls/libc-2.3.2.so)
==21928==    by 0x1BB11077: getservbyname (in /lib/tls/libc-2.3.2.so)
==21928==    by 0x1B92782F: mysql_server_init (in /usr/lib/libmysqlclient.so.14.0.0)
==21928==
==21928== LEAK SUMMARY:
==21928==    definitely lost: 30 bytes in 2 blocks.
==21928==      possibly lost: 0 bytes in 0 blocks.
==21928==    still reachable: 0 bytes in 0 blocks.
==21928==         suppressed: 0 bytes in 0 blocks.

I haven't digged deeper so far.

Tomasz Buchert
thinred@o2.pl
[25 Jan 2006 1:52] Marcus Grando
I have same problem in FreeBSD / MySQL 4.1 Client...

Any news about that? Without that i can't running daemon with threads...

==72446== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==72446== malloc/free: in use at exit: 56569 bytes in 517 blocks.
==72446== malloc/free: 1484 allocs, 967 frees, 767143 bytes allocated.
==72446== For counts of detected errors, rerun with: -v
==72446== searching for pointers to 517 not-freed blocks.
==72446== checked 4142980 bytes.
==72446== 
==72446== 49 bytes in 5 blocks are definitely lost in loss record 2 of 17
==72446==    at 0x3C032183: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
==72446==    by 0x3C37C823: strdup (in /lib/libc.so.6)
==72446==    by 0x3C376B1E: _nsyylex (in /lib/libc.so.6)
==72446==    by 0x3C375FA4: _nsyyparse (in /lib/libc.so.6)
==72446==    by 0x3C379A65: _nsdispatch (in /lib/libc.so.6)
==72446==    by 0x3C378E87: (within /lib/libc.so.6)
==72446==    by 0x3C379223: gethostbyname (in /lib/libc.so.6)
==72446==    by 0x3C08154B: my_gethostbyname_r (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x3C08BE8B: mysql_real_connect (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x804A3BF: my_dbconnect (mysql.c:14)
==72446==    by 0x804AC88: main_thread (blogmail.c:58)
==72446==    by 0x3C03A692: (within /usr/local/lib/valgrind/libpthread.so.2)
==72446== 
==72446== 
==72446== 104 bytes in 2 blocks are definitely lost in loss record 3 of 17
==72446==    at 0x3C03294B: calloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so)
==72446==    by 0x3C078E80: my_thread_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x3C078FC8: my_thread_global_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x3C074AF6: my_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x3C06EE25: mysql_server_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x3C08AD4F: mysql_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14)
==72446==    by 0x804A381: my_dbconnect (mysql.c:8)
==72446==    by 0x804AC88: main_thread (blogmail.c:58)
==72446==    by 0x3C03A692: (within /usr/local/lib/valgrind/libpthread.so.2)
==72446==    by 0xB8010B4F: (within /usr/local/lib/valgrind/stage2)
[3 Mar 2006 16:39] Nathanael Noblet
Just a confirmation that the bug exists in 5.0.18 for Fedora Core 5 (test3). 

I have a problem because we have virtual users that are using a pam module pam_mysql. With this memory leak after a few days 2GB of swap is consumed.

Is this being worked on?
[12 May 2006 6:07] Braden Temme
I am getting this same bug.  I recommend upgrading this bug report to 'S2 (Serious)'.
[16 May 2006 7:26] Alexander Barkov
This is not a bug. Hartmut is right that this is only one time "memory leak",
it is not something which is accumulated through calling mysql_connect..mysql_close
in a loop.  Thus you can just ignore those 6K of memory not freed. It is not harmfull.

This program proves that:

#include <stdio.h>
#include <mysql.h>
static int one_time()
{
  MYSQL *connection,mysql;
  mysql_init(&mysql);
  connection=mysql_real_connect(&mysql,"localhost","root",NULL,"test",0,0,0);
  if( connection == NULL )
  {
    printf("%s", mysql_error(&mysql));
    return 1;
  }
  mysql_close(connection);
  return 0;
}
int main(void)
{
  int i;
  for (i= 0; i < 100; i++)
  {
    one_time();
  }
  return;
}

No mater the counter is 1 or 100, vagrind reports the same amount
of memory not freed.

Note, the same happens with any program using functions like
gethostbyname(). Functions of these family allocate some in-memory
cache to make subsequent calls faster. So, vagrind reports
some not-freed memory at the end of the program. But this is
not really *memory leak*.

libmysqlclient does the same:
character set information in not freed by mysql_clone() *intentionally*,
to make subsequent mysql_connect() or mysql_init() much faster.
which is important for things like PHP, or for pam modules.

I agree that it probably would be nice to have a special function to free all
memory allocated by libmysqlclient at a desired moment of time.
Something like mysql_free_library(). Feel free to post a feature  request for that.

As for PAM module eating 2GB memory, most likely it is the one who is leaking memory
itself. I suggest either report its authors or try to trace it somehow.
[16 May 2006 8:00] Sergei Golubchik
It is an expected and documented behaviour. See http://dev.mysql.com/doc/refman/5.0/en/c-api-function-overview.html

" Application programs should use this general outline for interacting with MySQL:

   1.

      Initialize the MySQL library by calling mysql_library_init(). The library can be either the mysqlclient C client library or the mysqld embedded server library, depending on whether the application was linked with the -libmysqlclient or -libmysqld flag.
   2.

      Initialize a connection handler by calling mysql_init() and connect to the server by calling mysql_real_connect().
   3.

      Issue SQL statements and process their results. (The following discussion provides more information about how to do this.)
   4.

      Close the connection to the MySQL server by calling mysql_close().
   5.

      End use of the MySQL library by calling mysql_library_end().

The purpose of calling mysql_library_init() and mysql_library_end() is to provide proper initialization and finalization of the MySQL library. For applications that are linked with the client library, they provide improved memory management. If you don't call mysql_library_end(), a block of memory remains allocated. (This does not increase the amount of memory used by the application, but some memory leak detectors will complain about it.) For applications that are linked with the embedded server, these calls start and stop the server."
[16 May 2006 9:20] Alexander Barkov
Sergey, thanks for your comment! I didn't know about mysql_library_end().
This is exactly what I mean here:

> I agree that it probably would be nice to have a special function to free all
> memory allocated by libmysqlclient at a desired moment of time.
> Something like mysql_free_library(). Feel free to post a feature  request for
> that.

so there is no a need for a feature request. The function already exists.