MySQL C 客戶端的內存泄漏問題

咱們的一個服務器軟件在線上環境運行時出現了內存緩慢增加的問題。

用valgrind測試 MySQL的C客戶端mysqlclient發現,它在正常的使用中會被valgrind報出存在內存泄漏。

1 正常使用場景

下面的代碼是使用mysqlclient讀取數據的最經常使用的代碼mysql

#include <mysql/mysql.h>
#include <stdio.h>

int main()
{
    MYSQL       *conn;
    MYSQL_RES   *result;
    MYSQL_ROW    row;
    char        *w;


    conn = mysql_init(NULL);
    mysql_real_connect(conn, "127.0.0.1", "root", "", "db_test", 3306, NULL, 0);

    mysql_query(conn, "select id from test");

    result = mysql_store_result(conn);
    if (result == NULL) {
        printf("%d:%s\n", mysql_errno(conn), mysql_error(conn));
        goto out;
    }

    while ((row = mysql_fetch_row(result))) {
        w = row[0];
    }

 out:
    mysql_free_result(result);
    mysql_close(conn);
    mysql_library_end();

    return 0;
}

   

上面的代碼用valgrind檢測內存泄漏輸出以下:sql

cobbliu@ubuntu:~/dev/test$ gcc -o mysql mysql.c -lmysqlclient
cobbliu@ubuntu:~/dev/test$ valgrind --leak-check=full --show-reachable=yes ./mysql
==4497== Memcheck, a memory error detector
==4497== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==4497== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==4497== Command: ./mysql
==4497==
==4497==
==4497== HEAP SUMMARY:
==4497==     in use at exit: 73,872 bytes in 21 blocks
==4497==   total heap usage: 84 allocs, 63 frees, 128,626 bytes allocated
==4497==
#
#        這兒忽略了一部分輸出
#
==4497== LEAK SUMMARY:
==4497==    definitely lost: 0 bytes in 0 blocks
==4497==    indirectly lost: 0 bytes in 0 blocks
==4497==      possibly lost: 0 bytes in 0 blocks
==4497==    still reachable: 73,872 bytes in 21 blocks
==4497==         suppressed: 0 bytes in 0 blocks
==4497==
==4497== For counts of detected and suppressed errors, rerun with: -v
==4497== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

  能夠看出,在正常的使用場景下,mysqlclient有一部份內存在 mysql_close() 以後並無被釋放。ubuntu

2 解決方法

stackoverflow上的一篇文章提出瞭解決方法:在 mysql_close() 以後調用 mysql_library_end() 來釋放 剩餘的內存空間 MySQL開發手冊對 mysql_library_end() 的描述以下:api

This function finalizes the MySQL library.
Call it when you are done using the library (for example, after disconnecting from the server).
The action taken by the call depends on whether your application is linked to the MySQL client library or the MySQL embedded server library.
For a client program linked against the libmysqlclient library by using the -lmysqlclient flag, mysql_library_end() performs some memory management to clean up.

  

3 效果檢驗服務器

在上面的示例代碼中加入 mysql_library_end() 函數:app

//codes 
    mysql_free_result(result);
    mysql_close(conn); 
    mysql_library_end();
// codes

  而後用valgrind檢測內存泄漏:函數

cobbliu@ubuntu:~/dev/test$ valgrind --leak-check=full --show-reachable=yes ./mysql
==4513== Memcheck, a memory error detector
==4513== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==4513== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==4513== Command: ./mysql
==4513==
==4513==
==4513== HEAP SUMMARY:
==4513==     in use at exit: 0 bytes in 0 blocks
==4513==   total heap usage: 84 allocs, 84 frees, 128,626 bytes allocated
==4513==
==4513== All heap blocks were freed -- no leaks are possible
==4513==
==4513== For counts of detected and suppressed errors, rerun with: -v
==4513== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

  能夠看出,已經沒有未釋放的內存了。post

 

因此對於daemon進程,若是頻繁地調用 mysql_init  mysql_close 的話,記得在 mysql_close 以後調用 mysql_library_end() 來釋放未被釋放的內存測試

 

Author: CobbLiu <cobblau@gmail.com>fetch

Date: 2014-05-05 13:42:21 CST

HTML generated by org-mode 6.33x in emacs 23

相關文章
相關標籤/搜索