Все функции, упомянутые в этом блоке, являются библиотечными функциями. Как я могу исправить эту утечку памяти?
Он указан в категории « Все еще достижимо ». (Есть еще 4, которые очень похожи, но разных размеров)
630 bytes in 1 blocks are still reachable in loss record 5 of 5
at 0x4004F1B: calloc (vg_replace_malloc.c:418)
by 0x931CD2: _dl_new_object (dl-object.c:52)
by 0x92DD36: _dl_map_object_from_fd (dl-load.c:972)
by 0x92EFB6: _dl_map_object (dl-load.c:2251)
by 0x939F1B: dl_open_worker (dl-open.c:255)
by 0x935965: _dl_catch_error (dl-error.c:178)
by 0x9399C5: _dl_open (dl-open.c:584)
by 0xA64E31: do_dlopen (dl-libc.c:86)
by 0x935965: _dl_catch_error (dl-error.c:178)
by 0xA64FF4: __libc_dlopen_mode (dl-libc.c:47)
by 0xAE6086: pthread_cancel_init (unwind-forcedunwind.c:53)
by 0xAE61FC: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)
Поймать: Как только я запустил мою программу, она не дала утечек памяти, но у нее была еще одна строка в выводе Valgrind, которой раньше не было:
Отказ от символов в 0x5296fa0-0x52af438 в /lib/libgcc_s-4.4.4-20100630.so.1 из-за munmap ()
Если утечка не может быть устранена, может кто-нибудь хотя бы объяснить, почему строка munmap () заставляет Valgrind сообщать 0 «все еще достижимых» утечек?
Редактировать:
Вот минимальный тестовый образец:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *runner(void *param) {
/* some operations ... */
pthread_exit(NULL);
}
int n;
int main(void) {
int i;
pthread_t *threadIdArray;
n=10; /* for example */
threadIdArray = malloc((n+n-1)*sizeof(pthread_t));
for(i=0;i<(n+n-1);i++) {
if( pthread_create(&threadIdArray[i],NULL,runner,NULL) != 0 ) {
printf("Couldn't create thread %d\n",i);
exit(1);
}
}
for(i=0;i<(n+n-1);i++) {
pthread_join(threadIdArray[i],NULL);
}
free(threadIdArray);
return(0);
}
Бежать с:
valgrind -v --leak-check=full --show-reachable=yes ./a.out
Ответы:
Существует несколько способов определения «утечки памяти». В частности, есть два основных определения «утечки памяти», которые широко используются программистами.
Первое обычно используемое определение «утечки памяти»: «Память была выделена и впоследствии не была освобождена до завершения программы». Тем не менее, многие программисты (справедливо) утверждают, что некоторые типы утечек памяти, которые соответствуют этому определению, на самом деле не создают никаких проблем, и поэтому не должны рассматриваться как настоящие «утечки памяти».
Возможно, более строгое (и более полезное) определение «утечки памяти» таково: «Память была выделена и впоследствии не может быть освобождена, поскольку у программы больше нет указателей на выделенный блок памяти». Другими словами, вы не можете освободить память, на которую у вас больше нет указателей. Поэтому такая память является «утечкой памяти». Valgrind использует это более строгое определение термина «утечка памяти». Это тип утечки, который потенциально может вызвать значительное истощение кучи, особенно для долгоживущих процессов.
Категория «все еще достижимая» в отчете об утечке Valgrind относится к выделениям, которые соответствуют только первому определению «утечки памяти». Эти блоки не были освобождены, но они могли быть освобождены (если бы программист захотел), потому что программа все еще отслеживала указатели на эти блоки памяти.
В общем, нет необходимости беспокоиться о «все еще доступных» блоках. Они не представляют собой проблему, которую могут вызвать настоящие утечки памяти. Например, обычно нет возможности исчерпать кучу из «все еще доступных» блоков. Это связано с тем, что эти блоки обычно являются одноразовыми, ссылки на которые хранятся в течение всего времени жизни процесса. Несмотря на то, что вы могли бы пройти и убедиться, что ваша программа освобождает всю выделенную память, это обычно не дает практической пользы, поскольку операционная система в любом случае восстановит всю память процесса после его завершения. Сравните это с правдой утечки памяти, которые, если оставить их незафиксированными, могут привести к тому, что процессу не хватит памяти, если он останется работать достаточно долго, или просто заставят процесс использовать гораздо больше памяти, чем необходимо.
Вероятно, единственный раз, когда полезно убедиться, что все распределения имеют совпадающие «освобождения», это если ваши инструменты обнаружения утечек не могут определить, какие блоки «все еще доступны» (но Valgrind может это сделать) или если ваша операционная система не восстанавливает все память завершающего процесса (все платформы, для которых Valgrind был перенесен для этого).
источник
munmap
вызвано в результате выгрузки общего объекта. И все ресурсы, используемые общим объектом, могут быть освобождены до его выгрузки. Это может объяснить, почему «все еще достижимые» освобождаются в этомmunmap
деле. Я просто спекулирую здесь, хотя. Здесь недостаточно информации, чтобы сказать наверняка.Поскольку внизу есть какая-то подпрограмма из семейства pthread (но я не знаю, какая именно), я думаю, что вы запустили какой-то поток как присоединяемый, который завершил выполнение.
Информация о состоянии выхода этого потока остается доступной, пока вы не позвоните
pthread_join
. Таким образом, память сохраняется в записи о потерях при завершении программы, но она все еще доступна, так как вы можете использоватьpthread_join
для доступа к ней.Если этот анализ верен, либо запустите эти потоки отдельно, либо присоединитесь к ним до завершения вашей программы.
Изменить : я запустил вашу программу примера (после некоторых очевидных исправлений), и у меня нет ошибок, но следующее
Поскольку эта
dl-
вещь во многом напоминает то, что вы видите, я предполагаю, что вы видите известную проблему, для которой есть решение в виде файла подавленияvalgrind
. Возможно, ваша система не обновлена, или ваш дистрибутив не поддерживает эти вещи. (Мой Ubuntu 10,4, 64-битный)источник
Вы, кажется, не понимаете, что
still reachable
значит.Все
still reachable
это не утечка. Вам не нужно ничего делать с этим.источник
FILE
указателей?Вот правильное объяснение «все еще достижимо»:
«По-прежнему достижимы» - утечки, назначенные глобальным и статически-локальным переменным. Поскольку valgrind отслеживает глобальные и статические переменные, он может исключать выделения памяти, которые назначаются «однажды и забудь». Глобальная переменная назначала распределение один раз и никогда не переназначала, что распределение обычно не является «утечкой» в том смысле, что оно не увеличивается бесконечно. В строгом смысле это все еще утечка, но обычно ее можно игнорировать, если только вы не педантичны.
Локальные переменные, которым назначены распределения, а не free'd, почти всегда имеют утечки.
Вот пример
Valgrind будет сообщать о working_buf как «все еще достижимо - 16k», а temp_buf как «определенно потеряно - 5k».
источник
Для будущих читателей «Все еще доступный» может означать, что вы забыли закрыть что-то вроде файла. Хотя в первоначальном вопросе это не так, вы всегда должны убедиться, что сделали это.
источник