YAMD mini-HOWTO

Отслеживание проблем с распределением памяти при помощи YAMD

[Валентин Нечаев (netch@segfault.kiev.ua)]

YAMD. Рассказ от Aleksey Cheusov

Поскольку valgrind у меня иногда вылетает, я использую вместо него YAMD+efence. Но хочу сказать, что YAMD не обязательно самый продвинутый. Просто мне в своё время надоело искать и я остановился на том, что меня устраивает и мои поиски закончились.

YAMD:

  • Он маленький и в случае чего нетрудно будет разобраться где и что не так.
  • Нет необходимости в перекмпиляции/линковки программ для вылавливания багов при работе с памятью по крайней мере на платформах, где есть LD_PRELOAD (ELF).
  • В нем несколько программ, но полезная ДЛЯ МЕНЯ только одна. run-yamd

Пример:

   run-yamd -o /tmp/dictd.mem ./dictd --test apple
  

Это дело вываливает мне "простыню" типа

 <бесполезная шапка>
 INFO: Normal allocation of this block
 Address 0x40023fd4, size 44
 Allocated by malloc at
        /lib/libc.so.6(malloc+0x2f)[0x400c9eaf]
        ./dictd(strcpy+0xcbf7)[0x8057133]
        ./dictd(strcpy+0xcda8)[0x80572e4]
        ./dictd(strcpy+0xce4c)[0x8057388]
        ./dictd(strcpy+0x10c1f)[0x805b15b]
        ./dictd(strcpy+0x10c44)[0x805b180]
        ./dictd(strcpy+0x108fb)[0x805ae37]
        ./dictd(strcpy+0x1a36)[0x804bf72]
        ./dictd(strcpy+0x1ca2)[0x804c1de]
        /lib/libc.so.6(__libc_start_main+0xbe)[0x400737ee]
        ./dictd(strcpy+0x35)[0x804a571]

INFO: Normal deallocation of this block
Address 0x4018eff0, size 16
Allocated by malloc at
        /lib/libc.so.6(malloc+0x2f)[0x400c9eaf]
        ./dictd(strcpy+0xcbf7)[0x8057133]
        ./dictd(strcpy+0xcf64)[0x80574a0]
        ./dictd(strcpy+0xd0cc)[0x8057608]
        ./dictd(strcpy+0x10125)[0x805a661]
        ./dictd(strcpy+0x10919)[0x805ae55]
        ./dictd(strcpy+0x1a36)[0x804bf72]
        ./dictd(strcpy+0x1ca2)[0x804c1de]
        /lib/libc.so.6(__libc_start_main+0xbe)[0x400737ee]
        ./dictd(strcpy+0x35)[0x804a571]
    Freed by free at
        /lib/libc.so.6(__libc_free+0x2f)[0x400ca92f]
        ./dictd(strcpy+0xccba)[0x80571f6]
        ./dictd(strcpy+0xce90)[0x80573cc]
        ./dictd(strcpy+0xd063)[0x805759f]
        ./dictd(strcpy+0x10125)[0x805a661]
        ./dictd(strcpy+0x1092b)[0x805ae67]
        ./dictd(strcpy+0x1a36)[0x804bf72]
        ./dictd(strcpy+0x1ca2)[0x804c1de]
        /lib/libc.so.6(__libc_start_main+0xbe)[0x400737ee]
        ./dictd(strcpy+0x35)[0x804a571]

WARNING: Free of null pointer
At
        /lib/libc.so.6(__libc_free+0x2f)[0x400ca92f]
        /lib/libc.so.6(_dl_close+0x57b)[0x4015682b]
        /lib/libdl.so.2(dlopen+0x6b)[0x4017e4cb]
        ??:0(??)[0x4000b5a0]
        /lib/libdl.so.2(dlerror+0x290)[0x4017e8b0]
        /lib/libdl.so.2(dlclose+0x21)[0x4017e4f1]
        /usr/lib/libltdl.so.3(lt_dlseterror+0x302)[0x4002bb82]
        /usr/lib/libltdl.so.3(lt_dlclose+0xb9)[0x4002e5a9]
        ./dictd(strcpy+0xb7f6)[0x8055d32]
        ./dictd(strcpy+0x1119)[0x804b655]
        ./dictd(strcpy+0x1333)[0x804b86f]
        ./dictd(strcpy+0x2505)[0x804ca41]
        /lib/libc.so.6(__libc_start_main+0xbe)[0x400737ee]
        ./dictd(strcpy+0x35)[0x804a571]
    Attempt to free null pointer
        
WARNING: Memory leak
Address 0x42770fe4, size 28
Allocated by malloc at
        /lib/libc.so.6(malloc+0x2f)[0x400c9eaf]
        /lib/libc.so.6(textdomain+0x62a)[0x40081f4a]
        /lib/libc.so.6(textdomain+0x79e)[0x400820be]
        /lib/libc.so.6(textdomain+0x79e)[0x400820be]
        /lib/libc.so.6(ngettext+0x217)[0x40080b07]
        /lib/libc.so.6(gettext+0x845)[0x4007fd55]
        /lib/libc.so.6(__dcgettext+0x2d)[0x4007f4cd]
        /lib/libc.so.6(__strerror_r+0x132)[0x400cf8b2]
        /lib/libc.so.6(strerror+0x2b)[0x400cf76b]
        /lib/libdl.so.2(dlerror+0xbf)[0x4017e6df]
        /usr/lib/libltdl.so.3(lt_dlseterror+0x395)[0x4002bc15]
        /usr/lib/libltdl.so.3(lt_dlsym+0x30f)[0x4002e96f]
        ./dictd(strcpy+0xb4f6)[0x8055a32]
        ./dictd(strcpy+0xb6c0)[0x8055bfc]
        ./dictd(strcpy+0xeea)[0x804b426]
        ./dictd(strcpy+0xecf2)[0x805922e]
        ./dictd(strcpy+0x12e5)[0x804b821]
        ./dictd(strcpy+0x24b4)[0x804c9f0]
        /lib/libc.so.6(__libc_start_main+0xbe)[0x400737ee]
        ./dictd(strcpy+0x35)[0x804a571]

WARNING: Total memory leaks:
2008 unfreed allocations totaling 91268 bytes
        
*** Finished at Wed Dec  4 12:36:04 2002
Allocated a grand total of 418487 bytes
2410 allocations
Average of 173 bytes per allocation
Max bytes allocated at one time: 398226
29176 K alloced internally / 11744 K mapped now / 10972 K max
Virtual program size is 32592 K
End.

Выше только адреса. Для получения по ним имен функций со строками нужно воспользоваться утилитой do-syms:

  do-syms ./dictd < /tmp/dictd.mem > /tmp/dictd.mem2
Получаем что-то вроде
INFO: Normal allocation of this block
Address 0x40023fd4, size 44
Allocated by malloc at
        /lib/libc.so.6(malloc+0x2f) ??:0
        ./dictd(strcpy+0xcbf7) /shared/cheusov/prjs/dictd1/libmaa/xmalloc.c:40
        ./dictd(strcpy+0xcda8) /shared/cheusov/prjs/dictd1/libmaa/hash.c:80
        ./dictd(strcpy+0xce4c) /shared/cheusov/prjs/dictd1/libmaa/hash.c:127
        ./dictd(strcpy+0x10c1f) /shared/cheusov/prjs/dictd1/libmaa/timer.c:47
        ./dictd(strcpy+0x10c44) /shared/cheusov/prjs/dictd1/libmaa/timer.c:57
        ./dictd(strcpy+0x108fb) /shared/cheusov/prjs/dictd1/libmaa/maa.c:36
        ./dictd(strcpy+0x1a36) /shared/cheusov/prjs/dictd1/dictd.c:925
        ./dictd(strcpy+0x1ca2) /shared/cheusov/prjs/dictd1/dictd.c:1064
        /lib/libc.so.6(__libc_start_main+0xbe) ??:0
        ./dictd(strcpy+0x35) ??:0

do-syms использует addr2line.

НО Я ПРЕДУПРЕЖДАЮ, ЧТО РОДНАЯ ВЕРСИЯ do-syms на Linux НЕ РАБОТАЕТ. Поэтому я написал свою на shell: http://www.mova.org/~cheusov/pub/do-syms

Если программа слинкована динамически, то addr2line не работает. Можно прикрутить к do-syms gdb с breakpoint на _init и эти проблемы решаются. В ближайшее время этим займусь.

Всю необходимую мне статистику я лично собираю скриптами. Memory leaks собираю, например, так

  awk '/Memory leak/, /^$/' < /tmp/dictd.mem2

Опять же, скриптами можно отсеить memory leaks системных функций, например setlocale в glibc2.2.

Статья взята с сайта OpenNET.

[ опубликовано 11/02/2004 ]

Валентин Нечаев (netch@segfault.kiev.ua) - YAMD mini-HOWTO   Версия для печати