2013-02-06 1 views
1

Я пишу демона в C++, у него есть простая задача вставить некоторые события в базу данных mysql.Обнаружение утечки памяти с помощью Valgrind

Когда я побежал верхнюю команду, я увидел, что память processe нуждается в увеличении, я думал, что утечка памяти, и я начал использовать Valgrind

Я побежал Valgrind, как это:

Valgrind - инструмент = MemCheck --leak проверка = да --show-достижимые = да --num-звонящие = 20 --track-FDS = да ./my_app

я получаю следующее сообщение:

==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) 

Функция write_db заключается в следующем:

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; 
    } 
} 

Где утечка памяти? Я использую mysql_init и закрываю, как говорится в документации ... Может ли это быть ложным положительным?

+4

Существует потенциал для утечки памяти, если 'mysql_real_connect()' возвращает 'NULL'. Затем вы потеряли указатель на объект, возвращаемый 'mysql_init()'. – Angew

ответ

2

Поскольку вы используете connect только внутри своей функции, проще не выделять ее динамически и не подвергать риску утечку памяти (скорее всего, тот, который вы видите). Кроме того, API MySQL является C API и не бросает никаких исключений для вас, чтобы уловить, что упростит то, что у вас сейчас есть;

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; 
} 

Конечно, это все еще не учитывает обработку ошибок, которые вам нужно будет добавить назад.

+0

Я до сих пор получаю такую ​​же ошибку! – opc0de

+0

@ opc0de Если ошибка находится в одном и том же месте и отображается только при первом вызове, это, по-видимому, является чем-то внутренним для библиотеки MySQL (т. Е., Скорее всего, будет обрабатываться как ложный положительный результат). Оно появляется один раз для каждого вызов функции или один раз при первом вызове mysql_init? –

+0

каждый звонок ... Я думаю, что это ложный позитив – opc0de

1

mysql_init возвращает куча выделенного объекта, который должен быть освобожден mysql_close. В случае, когда что-то между mysql_init и mysql_close вызывает исключение, вы никогда не вызываете закрытие. Быстрое исправление - добавьте mysql_close в блок catch. Лучшее исправление - узнайте/используйте RAII.

Как указал Анже, на самом деле, вероятно, вы, скорее всего, испытываете утечку соединения при вызове mysql_real_connect (если только вы не видите текст исключения в журнале). Вы можете использовать RAII, чтобы избежать этого.

+0

Вы частично правы. «частично», потому что этот шов является C API, и здесь нет никаких исключений. Скорее всего, некоторые функции между 'mysql_init' и' mysql_close' терпят неудачу и недействительны «дескриптор». –

+0

Yeh, я понял, прочитав комментарий Ангела. Еще просыпаюсь :) – jmetcalfe