GLIBC ( ГЛИБЦ ):отладка утечек памяти:как интерпретировать выходные данные mtrace()

StackOverflow https://stackoverflow.com/questions/153953

  •  03-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь отладить проблему с утечкой памяти.Я использую mtrace() чтобы получить трассировку malloc / free / realloc.Я запустил свою программу, и теперь у меня есть огромный файл журнала.Пока все идет хорошо.Но у меня возникли проблемы с интерпретацией файла.Посмотрите на эти строки:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64

Странным в этом является то, что один вызов (тот же обратный адрес) отвечает за 4 распределения.

Еще более странный:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80

Между этими двумя строками блок 0x2aaab43a1700 никогда не освобождается.

Кто-нибудь знает, как это объяснить?Как один вызов может привести к выделению 4 единиц?И как malloc мог вернуть адрес, который уже был выделен ранее?

редактировать 2008/09/30:Скрипт для анализа выходных данных mtrace (), предоставленный GLIBC (mtrace.pl), здесь ничем не поможет.Он просто скажет:Выделите дубликат 0x2aaab43a1700.Но как это могло произойти?

Это было полезно?

Решение

Функция, выделяющая память, вызывается более одного раза.Адрес вызывающего абонента указывает на код, который выполнил выделение, и этот код просто выполняется более одного раза.

Вот пример на языке Си:

void *allocate (void)
{
  return (malloc(1000));
}

int main()
{
  mtrace();
  allocate();
  allocate();
}

Результатом работы mtrace является:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at 0x4004f6
0x0000000000601850    0x3e8  at 0x4004f6

Обратите внимание, насколько идентичен адрес вызывающего абонента?Вот почему скрипт, анализирующий mtrace, говорит, что они идентичны, потому что одна и та же ошибка обнаруживается более одного раза, что приводит к нескольким утечкам памяти.

Компиляция с флагами отладки (-g) полезна, если вы можете:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000000000601460    0x3e8  at /home/andrjohn/development/playground/test.c:6
0x0000000000601850    0x3e8  at /home/andrjohn/development/playground/test.c:6

Другие советы

Вы смотрите на прямой вывод mtrace, который чрезвычайно запутан и противоречит здравому смыслу.К счастью, существует perl-скрипт (называемый mtrace, найденный в glibc-utils), который может очень легко помочь в синтаксическом анализе этого вывода.

Скомпилируйте свою сборку с включенной отладкой и запустите mtrace следующим образом:

$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out

Memory not freed:
-----------------
   Address     Size     Caller
0x094d9378    0x400  at test.c:6

Результатом должно быть лот легче усваивается.

Одно из возможных объяснений заключается в том, что одна и та же функция выделяет разные размеры буфера?Одним из таких примеров является strdup .

Что касается второго вопроса, возможно, что среда выполнения выделяет некоторую "статическую" область очистки, которая не предназначена для освобождения до тех пор, пока процесс не будет завершен.И в этот момент операционная система все равно произведет очистку после завершения процесса.

Подумайте об этом с другой стороны:в Java нет деструкторов и нет гарантий, что финализация когда-либо будет вызвана для какого-либо объекта.

Попробуйте запустить свое приложение под управлением valgrind.Это могло бы дать вам лучшее представление о том, что на самом деле происходит утечка.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top