GLIBC: отладка утечек памяти: как интерпретировать вывод mtrace () - PullRequest
5 голосов
/ 30 сентября 2008

Я пытаюсь отладить проблему утечки памяти. Я использую 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), здесь не поможет. Он просто скажет: Alloc 0x2aaab43a1700 дублировать. Но как это могло произойти?

Ответы [ 4 ]

8 голосов
/ 30 сентября 2008

Вы смотрите на прямой вывод 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

Вывод должен быть лот легче переварить.

5 голосов
/ 04 октября 2008

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

Вот пример на C:

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
0 голосов
/ 30 сентября 2008

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

0 голосов
/ 30 сентября 2008

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

По второму вопросу, возможно, во время выполнения выделяется некоторая «статическая» область царапин, которая не предназначена для освобождения, пока процесс не будет завершен. И в этот момент ОС все равно будет очищаться после процесса.

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

...