rubyists-
this is really simplistic, and only works with glibc systems (includes
most/all linuxes) having an addr2line program, but here’s a little memory leak
detecting scheme which works with c and c++
add this to your c sources…
#include “leaks.h”
and recompile with ‘-g’ <<-- IMPORTANT!!!
run c programs/ruby code using c extension, this will attempt to write the
file ‘./mtrace.log’ in the current directory, so be sure you have write
permissions there!
after the run do
mtrace.rb ./a.out ./mtrace.log /usr/bin/addr2line
note that the above are the default arguments so if those values are correct
you only need do
mtrace.rb
EXAMPLE
for this c++ program
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include “leaks.h”
4
5
6 void *
7 leak0 (void)
8 {
9 return malloc (1);
10 }
11
12
13 class Foo
14 {
15 public:
16 Foo ()
17 {
18 };
19 long l;
20 };
21
22
23
24 int
25 main (int argc, char **argv)
26 {
27
28 int i;
29 void *a, *b;
30 Foo *foo;
31
32 b = malloc (1);
33 free (b);
34 a = malloc (1);
35 a = malloc (1);
36
37 b = leak0 ();
38 free (b);
39 a = leak0 ();
40 a = leak0 ();
41
42 foo = new Foo ();
43 delete foo;
44 foo = new Foo ();
45
46 return 1;
47 }
the output will be
POTENTIAL LEAKS
-
[0x4005e224] 0x0804a048 → 0x00000004
@ [0x080489a5] frame 0 a.out(backtrace_symbols+0x1d5) [0x80489a5] /home/ahoward/eg/c/leak/leaks.h:65
@ [0x401673ad] frame 1 /lib/libc.so.6(malloc+0x2d) [0x401673ad] ??:0
@ [0x4005e224] frame 2 /usr/local/lib/libstdc++.so.3(_Znwj+0x24) [0x4005e224] ??:0
@ [0x08048c72] frame 3 a.out [0x8048c72] /home/ahoward/eg/c/leak/leak_driver.cc:42
@ [0x40107336] frame 4 /lib/libc.so.6(__libc_start_main+0x8e) [0x40107336] ??:0
@ [0x08048821] frame 5 a.out(_Unwind_Resume+0x31) [0x8048821] ??:0 -
[0x08048b70] 0x0804a038 → 0x00000001
@ [0x080489a5] frame 0 a.out(backtrace_symbols+0x1d5) [0x80489a5] /home/ahoward/eg/c/leak/leaks.h:65
@ [0x401673ad] frame 1 /lib/libc.so.6(malloc+0x2d) [0x401673ad] ??:0
@ [0x08048b70] frame 2 a.out(__gxx_personality_v0+0x420) [0x8048b70] /home/ahoward/eg/c/leak/leak_driver.cc:11
@ [0x08048be7] frame 3 a.out [0x8048be7] /home/ahoward/eg/c/leak/leak_driver.cc:38
@ [0x40107336] frame 4 /lib/libc.so.6(__libc_start_main+0x8e) [0x40107336] ??:0
@ [0x08048821] frame 5 a.out(_Unwind_Resume+0x31) [0x8048821] ??:0 -
[0x08048b70] 0x0804a028 → 0x00000001
@ [0x080489a5] frame 0 a.out(backtrace_symbols+0x1d5) [0x80489a5] /home/ahoward/eg/c/leak/leaks.h:65
@ [0x401673ad] frame 1 /lib/libc.so.6(malloc+0x2d) [0x401673ad] ??:0
@ [0x08048b70] frame 2 a.out(__gxx_personality_v0+0x420) [0x8048b70] /home/ahoward/eg/c/leak/leak_driver.cc:11
@ [0x08048bdf] frame 3 a.out [0x8048bdf] /home/ahoward/eg/c/leak/leak_driver.cc:37
@ [0x40107336] frame 4 /lib/libc.so.6(__libc_start_main+0x8e) [0x40107336] ??:0
@ [0x08048821] frame 5 a.out(_Unwind_Resume+0x31) [0x8048821] ??:0 -
[0x08048bbe] 0x0804a018 → 0x00000001
@ [0x080489a5] frame 0 a.out(backtrace_symbols+0x1d5) [0x80489a5] /home/ahoward/eg/c/leak/leaks.h:65
@ [0x401673ad] frame 1 /lib/libc.so.6(malloc+0x2d) [0x401673ad] ??:0
@ [0x08048bbe] frame 2 a.out [0x8048bbe] /home/ahoward/eg/c/leak/leak_driver.cc:33
@ [0x40107336] frame 3 /lib/libc.so.6(__libc_start_main+0x8e) [0x40107336] ??:0
@ [0x08048821] frame 4 a.out(_Unwind_Resume+0x31) [0x8048821] ??:0 -
[0x08048bae] 0x0804a008 → 0x00000001
@ [0x080489a5] frame 0 a.out(backtrace_symbols+0x1d5) [0x80489a5] /home/ahoward/eg/c/leak/leaks.h:65
@ [0x401673ad] frame 1 /lib/libc.so.6(malloc+0x2d) [0x401673ad] ??:0
@ [0x08048bae] frame 2 a.out [0x8048bae] /home/ahoward/eg/c/leak/leak_driver.cc:32
@ [0x40107336] frame 3 /lib/libc.so.6(__libc_start_main+0x8e) [0x40107336] ??:0
@ [0x08048821] frame 4 a.out(_Unwind_Resume+0x31) [0x8048821] ??:0
CONFIRMED LEAKS
the ‘+’ indicates a malloc which was never freed, note that this is not always
a leak since some resources might me mallocd once per process and freed on
exit! however, in this program they all are, in fact, leaks. examine the
stack trace for each leak, it shows the file name and line number for each
call on the stack, some of them cannot be resolved (system files) but the
one’s in our program can, IFF you compile with -g, i included the line numbers
in the source - check it out - every leak is detected acurately.
the sources are available from
http://eli/lib/ruby/site_ruby/leak/leak.tgz
try them out with
tar xvfz leak.tgz
cd leak
make
they are very simple and have NO error detection.
however, they are simple enough to hack up yourself into a reasonable memory
leak detection scheme… have at it.
if anyone feels like improving these, please send me the improvments, i’m sure
there are MANY to be made.
-ara
···
–
====================================
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================