cynthia / gperftools

Automatically exported from code.google.com/p/gperftools
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

heapcheck doesn't work on os x #389

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

Let's say we have this piece of code with a clear leak:

#include <stdlib.h>

void foo()
{
  char *tmp;
  tmp = (char *) malloc(sizeof(char)*10);
}

int main()
{
  foo();
  return 0;
}

What is the expected output? 

I would expect to see something from the heapcheck code. But I don't get any 
output at all.

What do you see instead?

No output.

What version of the product are you using? On what operating system?
Tried both 1.8 and latest 1.9.1.
OS: Lion 10.7.2 - Darwin Kernel Version 11.2.0

Please provide any additional information below.

The compilation and execution commands here:

$ gcc -I /Users/drio/tmp/gpt/include/google -L /Users/drio/tmp/gpt/lib  -g 
-ltcmalloc leak.c -o leak
$ HEAPCHECK=normal ./leak

Thanks!
-drd

Original issue reported on code.google.com by driodei...@gmail.com on 8 Jan 2012 at 4:40

GoogleCodeExporter commented 9 years ago
Some extra information. The binary generated is properly linked to the tcmalloc 
lib:

$ otool -L ./leak
./leak:
        /Users/drio/tmp/gpt/lib/libtcmalloc.0.dylib (compatibility version 4.0.0, current version 4.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

Original comment by driodei...@gmail.com on 8 Jan 2012 at 6:49

GoogleCodeExporter commented 9 years ago
Mysterious.  It should at least print out a message 'no leaks found' at the end 
of program execution.

I think the best next step is to run in a debugger to see what's going on.  It 
would be good to step into the malloc call to see if it eventually ends up at 
tc_malloc.  (Or put a breakpoint at tc_malloc and see if it's hit.)  And also 
put a breakpoint in the destructor in heap-checker.cc -- I think it's actually 
in heap-checker-bcad.cc -- that causes the leak-checking to happen at the end 
of the file, and see if that is triggering.

Original comment by csilv...@gmail.com on 9 Jan 2012 at 3:15

GoogleCodeExporter commented 9 years ago
Thanks for the quick answer!

The break point in tc_malloc confirms that the profile code gets executed:

(gdb) b tc_malloc
Breakpoint 2 at 0x10001a1dd: file tcmalloc.cc, line 1483.
(gdb) r
Starting program: /private/tmp/leak 

Breakpoint 2, tc_malloc (size=1) at tcmalloc.cc:1483
1483    extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
(gdb) where
#0  tc_malloc (size=1) at tcmalloc.cc:1483
#1  0x000000010000618c in TCMallocGuard::TCMallocGuard (this=0x1) at 
tcmalloc.cc:892
#2  0x000000010000629e in __static_initialization_and_destruction_0 [inlined] 
() at /Users/drio/tmp/google-perftools-1.9.1/src/tcmalloc.cc:907
#3  0x000000010000629e in global constructors keyed to cfree () at 
tcmalloc.cc:1643
#4  0x00007fff5fc0fd1a in 
__dyld__ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE 
()
#5  0x00007fff5fc0fa66 in 
__dyld__ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE ()
#6  0x00007fff5fc0d258 in 
__dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21Initi
alizerTimingListE ()
#7  0x00007fff5fc0d1f1 in 
__dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21Initi
alizerTimingListE ()
#8  0x00007fff5fc0e02b in 
__dyld__ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTim
ingListE ()
#9  0x00007fff5fc034ad in __dyld__ZN4dyld24initializeMainExecutableEv ()
#10 0x00007fff5fc07580 in __dyld__ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_ ()
#11 0x00007fff5fc01059 in __dyld__dyld_start ()
Current language:  auto; currently c++

Also, I set up a breakpoint in HeapLeakChecker::HeapLeakChecker() but that code 
doesn't seem to be executed:

(gdb) b HeapLeakChecker::HeapLeakChecker()
Function "HeapLeakChecker::HeapLeakChecker()" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (HeapLeakChecker::HeapLeakChecker()) pending.
(gdb) r
Starting program: /private/tmp/leak 
Reading symbols for shared libraries ++++......................... done

What do you suggest to do next?

-drd

Original comment by driodei...@gmail.com on 9 Jan 2012 at 10:01

GoogleCodeExporter commented 9 years ago
Suspicious that the tc_malloc breakpoint didn't say "pending on shared library 
load" but the heap-checker breakpoint did.  I always get suspicious when it 
says a breakpoint is 'pending' rather than actually present.  After you run, 
and look at the breakpoints again, is the breakpoint still pending, or did it 
actually load?

You could also try doing something like
   print getenv("HEAPCHECK")
somewhere in the gdb run (at the tc_malloc breakpoint perhaps) to see if that 
part worked.

I'm suspicious that maybe the environment-reading code is the culprit.  Take a 
look at the code near the top of sysinfo.cc that tries to read from the 
environment -- maybe it's having trouble on your setup (something to do with 
/proc, perhaps)?  May be worthwhile to single-step through it.

Also, did you try the suggestion of running 'make check'?  Do the heapcheck 
tests pass there?

Original comment by csilv...@gmail.com on 10 Jan 2012 at 3:17

GoogleCodeExporter commented 9 years ago
> Suspicious that the tc_malloc breakpoint didn't say "pending on shared 
library load" but the heap-checker  
> breakpoint did.  I always get suspicious when it says a breakpoint is 
'pending' rather than actually present.   After you run, and 
> look at the breakpoints again, is the breakpoint still pending, or did it 
actually load?

You are right. It couldn't resolve the address:

(gdb) b HeapLeakChecker::HeapLeakChecker()
Function "HeapLeakChecker::HeapLeakChecker()" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (HeapLeakChecker::HeapLeakChecker()) pending.
(gdb) r
Starting program: /private/tmp/leak 
Reading symbols for shared libraries ++++......................... done

Program exited normally.
(gdb) info breakpoints 
Num Type           Disp Enb Address            What
1   breakpoint     keep y   <PENDING>          
HeapLeakChecker::HeapLeakChecker()

> You could also try doing something like
>  print getenv("HEAPCHECK")
> somewhere in the gdb run (at the tc_malloc breakpoint perhaps) to see if that 
part worked.

It seems that we read the ENV variable just fine:

(gdb) b tc_malloc
Breakpoint 1 at 0x20c49ba5e2a1dd: file tcmalloc.cc, line 1483.
(gdb) r
Starting program: /private/tmp/leak 
Reading symbols for shared libraries ++++......................... done

Breakpoint 1, tc_malloc (size=1) at tcmalloc.cc:1483
1483    extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
(gdb) print (char *) getenv("HEAPCHECK")
The program being debugged stopped while in a function called from GDB.
When the function (malloc) is done executing, GDB will silently
stop (instead of continuing to evaluate the expression containing
the function call).
$1 = 0x7fff5fbff8bc "normal"

> I'm suspicious that maybe the environment-reading code is the culprit.  Take 
a look at the code near the top of sysinfo.cc that tries to read from the 
environment -- 
> maybe it's having trouble on your setup (something to do with /proc, 
perhaps)?  May be worthwhile to single-step through it.

It seems that function doesn't get executed:

(gdb) b GetenvBeforeMain
Breakpoint 1 at 0x3126e978d4a621
Breakpoint 2 at 0x3126e978d4e360
Breakpoint 3 at 0x20c49ba5e27c91
Breakpoint 4 at 0x20c49ba5e57d00
warning: Multiple breakpoints were set.
Use the "delete" command to delete unwanted breakpoints.
(gdb) r
Starting program: /private/tmp/leak 
Reading symbols for shared libraries ++++......................... done

> Also, did you try the suggestion of running 'make check'?  Do the heapcheck 
tests pass there?

Umm, the test did not pass, actually it gets stuck forever: 
https://gist.github.com/1591787

What do you think?

-drd

Original comment by driodei...@gmail.com on 10 Jan 2012 at 11:10

GoogleCodeExporter commented 9 years ago
Are you sure the test is repeating forever, and not just for a really long 
time?  How long did you wait for the test?  It may be that redirecting output 
to a file will make it go faster.

I think David is right that we just don't support the heap-checker for OS X.  I 
should have thought of that right away. :-(  The INSTALL file says:
   libtcmalloc.so successfully builds, and the "advanced" tcmalloc
   functionality all works except for the leak-checker, which has
   Linux-specific code:

I'm going to reword the bug to match this, and lower its priority.  
heap-checking is unlikely to be supported on os x unless someone wants to spend 
the time to make it work...

Original comment by csilv...@gmail.com on 13 Jan 2012 at 10:47

GoogleCodeExporter commented 9 years ago
I am removing mention of 'freebsd' from the title of this issue as heap 
checking on FreeBSD was supported as of releases google-perftools-1.9.1 and 
gperftools-2.0.

Also, if anyone is interested in doing the OS X porting work I would be more 
than happy to help out as I did the FreeBSD porting work.

Original comment by chapp...@gmail.com on 7 Feb 2012 at 3:14

GoogleCodeExporter commented 9 years ago
Can you outline, at high level, the steps required for the porting?

Original comment by driodei...@gmail.com on 7 Feb 2012 at 3:48

GoogleCodeExporter commented 9 years ago
You can get a general idea of what is required by taking a look at 
malloc_hook_mmap_linux.h and malloc_hook_mmap_freebsd.h. Most of your porting 
effort will involve writing one of these files for OS X. Yours will probably 
look more like the linux version than the FreeBSD version. Let me know if you 
have any further questions.

Original comment by chapp...@gmail.com on 2 Mar 2012 at 4:44

GoogleCodeExporter commented 9 years ago
Any luck here with the porting effort?

Original comment by chapp...@gmail.com on 21 Apr 2012 at 6:28

GoogleCodeExporter commented 9 years ago
No progress yet.

Original comment by driodei...@gmail.com on 21 Apr 2012 at 10:10

GoogleCodeExporter commented 9 years ago
Seems like I have a somewhat related issue, but the same actions as described 
above give me a segfault.

OSX 10.8.5
Apple LLVM version 5.0 (clang-500.2.76) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

<offtopic>
It is even worse since valgrind's memcheck also does not seem to work on osx 
10.8.x.
</offtopic>

Original comment by psych...@gmail.com on 17 Oct 2013 at 1:55