The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"утечка памяти"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"утечка памяти"  +/
Сообщение от metallic email on 21-Апр-10, 18:12 
Есть демон на Си, он обрабатывает поток netflow, суммирует трафик и складывает в базу. Суть проблемы в том, что подъедает память.
С помощью valgrind вычислил пару мелких утечек, устранил. Осталась основная, которую как исправить - не знаю и в чем она заключается - не пойму, т.к. визуально все в порядке. Вот вывод valgrind:

==39527== HEAP SUMMARY:
==39527==     in use at exit: 7,596,433 bytes in 2,786 blocks
==39527==   total heap usage: 46,982 allocs, 44,196 frees, 140,180,473 bytes allocated
==39527==
==39527== 22 bytes in 2 blocks are definitely lost in loss record 3 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0x1113A38: strdup (in /lib/libc.so.7)
==39527==    by 0x402C5E: ip_by_username (vpnms_functions.c:264)
==39527==    by 0x4030E1: clear_rules (vpnms_functions.c:395)
==39527==    by 0x4022B3: StopDaemon (vpnms_functions.c:36)
==39527==    by 0x40471A: vpnmsd_nf_thread (vpnmsd_nf_thread.c:78)
==39527==    by 0xF994D0: ??? (in /lib/libthr.so.3)
==39527==
==39527== 801 (16 direct, 785 indirect) bytes in 1 blocks are definitely lost in loss record 18 of 32
==39527==    at 0x2458AE: calloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0x401A1A: config_open (config.c:17)
==39527==    by 0x40240A: LoadConfig (vpnms_functions.c:84)
==39527==    by 0x4054B0: main (vpnmsd.c:233)
==39527==
==39527== 4,088 bytes in 1 blocks are possibly lost in loss record 24 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0xD298C2: my_once_alloc (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD29F8B: init_state_maps (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A894: init_available_charsets (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2AAC9: get_charset_by_csname (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3AFE8: mysql_init_character_set (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3CCF4: mysql_real_connect (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0x40290B: exec_query (vpnms_functions.c:167)
==39527==    by 0x405523: main (vpnmsd.c:247)
==39527==
==39527== 4,088 bytes in 1 blocks are possibly lost in loss record 25 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0xD298C2: my_once_alloc (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD299CA: my_once_strdup (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A34D: add_collation (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD392C8: my_xml_leave (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD39B04: my_xml_parse (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD32F71: my_parse_charset_xml (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A1CB: my_read_charset_file (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A8CF: init_available_charsets (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2AAC9: get_charset_by_csname (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3AFE8: mysql_init_character_set (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3CCF4: mysql_real_connect (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==
==39527== 8,176 bytes in 2 blocks are possibly lost in loss record 27 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0xD298C2: my_once_alloc (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD29F6F: init_state_maps (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A894: init_available_charsets (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2AAC9: get_charset_by_csname (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3AFE8: mysql_init_character_set (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3CCF4: mysql_real_connect (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0x40290B: exec_query (vpnms_functions.c:167)
==39527==    by 0x405523: main (vpnmsd.c:247)
==39527==
==39527== 12,264 bytes in 3 blocks are possibly lost in loss record 28 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0xD298C2: my_once_alloc (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A553: add_collation (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD392C8: my_xml_leave (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD39B56: my_xml_parse (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD32F71: my_parse_charset_xml (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A1CB: my_read_charset_file (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2A8CF: init_available_charsets (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2AAC9: get_charset_by_csname (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3AFE8: mysql_init_character_set (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3CCF4: mysql_real_connect (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0x40290B: exec_query (vpnms_functions.c:167)
==39527==
==39527== 106,080 bytes in 13 blocks are possibly lost in loss record 30 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0xD22901: my_malloc (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD2591D: alloc_root (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3B6D9: unpack_fields (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3C646: cli_read_query_result (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3AC6D: mysql_real_query (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0x40295F: exec_query (vpnms_functions.c:174)
==39527==    by 0x402B99: username_by_ip (vpnms_functions.c:236)
==39527==    by 0x404B58: vpnmsd_nf_thread (vpnmsd_nf_thread.c:166)
==39527==    by 0xF994D0: ??? (in /lib/libthr.so.3)
==39527==
==39527== 7,443,072 (143,520 direct, 7,299,552 indirect) bytes in 897 blocks are definitely lost in loss record 32 of 32
==39527==    at 0x24667B: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==39527==    by 0xD22901: my_malloc (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0xD3A79C: mysql_store_result (in /usr/local/lib/mysql/libmysqlclient.so.16)
==39527==    by 0x4029A8: exec_query (vpnms_functions.c:181)
==39527==    by 0x402B99: username_by_ip (vpnms_functions.c:236)
==39527==    by 0x404B58: vpnmsd_nf_thread (vpnmsd_nf_thread.c:166)
==39527==    by 0xF994D0: ??? (in /lib/libthr.so.3)
==39527==
==39527== LEAK SUMMARY:
==39527==    definitely lost: 143,558 bytes in 900 blocks
==39527==    indirectly lost: 7,300,337 bytes in 1,830 blocks
==39527==      possibly lost: 134,696 bytes in 20 blocks
==39527==    still reachable: 17,842 bytes in 36 blocks
==39527==         suppressed: 0 bytes in 0 blocks
==39527== Reachable blocks (those to which a pointer was found) are not shown.
==39527== To see them, rerun with: --leak-check=full --show-reachable=yes
==39527==
==39527== For counts of detected and suppressed errors, rerun with: -v
==39527== Use --track-origins=yes to see where uninitialised values come from
==39527== ERROR SUMMARY: 470 errors from 19 contexts (suppressed: 24 from 3)


Все сводится к ф-ии exec_query, вот ее код:


MYSQL_RES *exec_query(char *query)
{
   MYSQL_RES   *res;
   MYSQL       mysql;

   if ( 0 == strcasecmp (vpnms_config.vpnms_sql_debug, "yes") )
      syslog (LOG_DEBUG, "SQL: %s", query);

   mysql_init(&mysql);
   if (!mysql_real_connect(&mysql, vpnms_config.mysql_host, vpnms_config.mysql_username, vpnms_config.mysql_password,
         vpnms_config.mysql_database, vpnms_config.mysql_port, NULL, 0))
   {
      syslog (LOG_ERR, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));
      exit(EXIT_FAILURE);
   }

if ( mysql_real_query(&mysql, query, strlen(query)) )
{
      syslog (LOG_ERR, "Query failed: Error: %s\n", mysql_error(&mysql));
      exit(EXIT_FAILURE);
   }
free(query);

res = mysql_store_result(&mysql);

mysql_close(&mysql);

return res;
}

Если надо - могу выложить исходники полностью

Высказать мнение | Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "утечка памяти"  +/
Сообщение от Michael (??) on 21-Апр-10, 18:32 

>
>MYSQL_RES *exec_query(char *query)
>{
>  MYSQL_RES   *res;

перепишите функцию так, чтобы указатель на MYSQL_RES передавался аргументом и будет вам счастье.

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

3. "утечка памяти"  +/
Сообщение от metallic email on 22-Апр-10, 10:49 
>
>>
>>MYSQL_RES *exec_query(char *query)
>>{
>>  MYSQL_RES   *res;
>
>перепишите функцию так, чтобы указатель на MYSQL_RES передавался аргументом и будет вам
>счастье.

Не понял, можете подробнее пояснить?

>а вы этот res потом освобождаете ?
>
>mysql_store_result() reads the entire result of a query to the client, allocates
>a MYSQL_RES structure, and places the result into this structure.

Конечно, после каждого использования ф-ии exec_query


Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

5. "утечка памяти"  +/
Сообщение от Michael (??) on 22-Апр-10, 11:42 

>Не понял, можете подробнее пояснить?

ну вы сами-хоть поняли, что за код вы написали. постараюсь объяснить
когда вы вызываете функцию, то под ее переменные выделяется место в стеке, когда функция завершается указателю стека возвращается первоначальное значение, т.е. вы строго говоря возвращаете указатель на область с рандомными данныни.
да действительно велика вероятность, что значение в стеке не будет перезаписано к моменту, когда вы используете возвращаемое значение. но расчитывать на это не есть ъорошо

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

7. "утечка памяти"  +/
Сообщение от guest email(??) on 22-Апр-10, 11:59 
>ну вы сами-хоть поняли, что за код вы написали. постараюсь объяснить
>когда вы вызываете функцию, то под ее переменные выделяется место в стеке,
>когда функция завершается указателю стека возвращается первоначальное значение, т.е. вы строго
>говоря возвращаете указатель на область с рандомными данныни.
>да действительно велика вероятность, что значение в стеке не будет перезаписано к
>моменту, когда вы используете возвращаемое значение. но расчитывать на это не
>есть ъорошо

прочувствуйте разницу между
char buf[100];
...
return (&buf);

и

char *buf;
...
return (buf);

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

8. "утечка памяти"  +/
Сообщение от Michael (??) on 22-Апр-10, 12:26 

>прочувствуйте разницу между
>char buf[100];
>...
>return (&buf);
>

>
>char *buf;
>...
>return (buf);

точно. ступил

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

10. "утечка памяти"  +/
Сообщение от metallic email on 22-Апр-10, 12:59 
>
>>Не понял, можете подробнее пояснить?
>
>ну вы сами-хоть поняли, что за код вы написали. постараюсь объяснить
>когда вы вызываете функцию, то под ее переменные выделяется место в стеке,
>когда функция завершается указателю стека возвращается первоначальное значение, т.е. вы строго
>говоря возвращаете указатель на область с рандомными данныни.
>да действительно велика вероятность, что значение в стеке не будет перезаписано к
>моменту, когда вы используете возвращаемое значение. но расчитывать на это не
>есть ъорошо

т.е. лучше сделать, чтобы ф-ия ничего не возвращала, а лучше передавать ф-ии указатель на res и пусть ф-ия в него пихает данные, а потом завершает свою работу?

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

6. "утечка памяти"  +/
Сообщение от Michael (??) on 22-Апр-10, 11:46 

>Конечно, после каждого использования ф-ии exec_query

а возвращаемое значение функции mysql_free проверяете?

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

11. "утечка памяти"  +/
Сообщение от metallic email on 22-Апр-10, 13:01 
>
>>Конечно, после каждого использования ф-ии exec_query
>
>а возвращаемое значение функции mysql_free проверяете?

Ну вот пример кода, как я пользуюсь этой ф-ией:

       query = malloc(256);
        sprintf(query, "SELECT Subnet_Address, NetMask FROM `subnets`");

        res = exec_query(query);
        rows = mysql_num_rows(res);
        subnets = calloc(rows + 1, sizeof(struct s_subnets));

        while ((row = mysql_fetch_row(res)))
        {
            num_subnets++;
            subnets[num_subnets].address = inet_addr(row[0]);
            subnets[num_subnets].mask = inet_addr(row[1]);
        }
        mysql_free_result(res);


Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

2. "утечка памяти"  +/
Сообщение от Andrey (??) on 22-Апр-10, 07:21 
а вы этот res потом освобождаете ?

mysql_store_result() reads the entire result of a query to the client, allocates a MYSQL_RES structure, and places the result into this structure.

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

4. "утечка памяти"  +/
Сообщение от guest email(??) on 22-Апр-10, 11:19 
>Есть демон на Си, он обрабатывает поток netflow, суммирует трафик и складывает
>в базу. Суть проблемы в том, что подъедает память.

Есть вариант, что это разовая утечка из-за автоматического вызова mysql_library_init() при
первом mysql_init()

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

9. "утечка памяти"  +/
Сообщение от metallic email on 22-Апр-10, 12:58 
>>Есть демон на Си, он обрабатывает поток netflow, суммирует трафик и складывает
>>в базу. Суть проблемы в том, что подъедает память.
>
>Есть вариант, что это разовая утечка из-за автоматического вызова mysql_library_init() при
>первом mysql_init()

Нет, об этом я читал и знаю, что чуть-чуть от библиотеки остается мусора, но он не разрастается, а у меня идет постоянное пожирание оперативной памяти, за сутки может съесть 15Мб


Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

12. "утечка памяти"  +/
Сообщение от guest email(??) on 22-Апр-10, 13:40 
>Нет, об этом я читал и знаю, что чуть-чуть от библиотеки остается
>мусора, но он не разрастается, а у меня идет постоянное пожирание
>оперативной памяти, за сутки может съесть 15Мб

может попробывать

>res = mysql_store_result(&mysql);
>mysql_close(&mysql);

syslog(LOG_DEBUG, "store(%p)", res);
>return res;

s/mysql_free_resust/my_mysql_free_resust/g
void
my_mysql_free_resust(MYSQL_RES *res)
{
     syslog(LOG_DEBUG, "free(%p)", res);
     mysql_free_result(res);
}

и пытаться понять кто забыл сделать free

Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

13. "утечка памяти"  +/
Сообщение от metallic email on 22-Апр-10, 18:41 
Нашел ошибку, при определенных условиях res не освобождался, поправил, теперь, вроде, все хорошо. Спасибо всем, кто откликнулся.
Высказать мнение | Ответить | Правка | ^ | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Спонсоры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2022 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру