New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

heapcheck doesn't work on os x #392

Open
alk opened this Issue Aug 23, 2015 · 12 comments

Comments

Projects
None yet
1 participant
@alk
Contributor

alk commented Aug 23, 2015

Originally reported on Google Code with ID 389

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

Reported by driodeiros on 2012-01-08 16:40:14

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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)

Reported by driodeiros on 2012-01-08 18:49:23

Contributor

alk commented Aug 23, 2015

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)

Reported by driodeiros on 2012-01-08 18:49:23

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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.

Reported by csilvers on 2012-01-09 03:15:15

  • Labels added: Type-Defect, Priority-Medium
Contributor

alk commented Aug 23, 2015

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.

Reported by csilvers on 2012-01-09 03:15:15

  • Labels added: Type-Defect, Priority-Medium
@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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_21InitializerTimingListE
()
#7  0x00007fff5fc0d1f1 in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListE
()
#8  0x00007fff5fc0e02b in __dyld__ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE
()
#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

Reported by driodeiros on 2012-01-09 22:01:17

Contributor

alk commented Aug 23, 2015

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_21InitializerTimingListE
()
#7  0x00007fff5fc0d1f1 in __dyld__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListE
()
#8  0x00007fff5fc0e02b in __dyld__ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE
()
#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

Reported by driodeiros on 2012-01-09 22:01:17

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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?

Reported by csilvers on 2012-01-10 03:17:46

Contributor

alk commented Aug 23, 2015

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?

Reported by csilvers on 2012-01-10 03:17:46

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
> 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







Reported by driodeiros on 2012-01-10 23:10:39

Contributor

alk commented Aug 23, 2015

> 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







Reported by driodeiros on 2012-01-10 23:10:39

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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...

Reported by csilvers on 2012-01-13 22:47:51

  • Labels added: Type-Porting, Priority-Low
  • Labels removed: Type-Defect, Priority-Medium
Contributor

alk commented Aug 23, 2015

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...

Reported by csilvers on 2012-01-13 22:47:51

  • Labels added: Type-Porting, Priority-Low
  • Labels removed: Type-Defect, Priority-Medium
@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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.

Reported by chappedm on 2012-02-07 03:14:04

  • Status changed: Accepted
Contributor

alk commented Aug 23, 2015

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.

Reported by chappedm on 2012-02-07 03:14:04

  • Status changed: Accepted
@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
Can you outline, at high level, the steps required for the porting?

Reported by driodeiros on 2012-02-07 15:48:51

Contributor

alk commented Aug 23, 2015

Can you outline, at high level, the steps required for the porting?

Reported by driodeiros on 2012-02-07 15:48:51

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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.

Reported by chappedm on 2012-03-02 16:44:09

Contributor

alk commented Aug 23, 2015

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.

Reported by chappedm on 2012-03-02 16:44:09

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
Any luck here with the porting effort?

Reported by chappedm on 2012-04-21 18:28:24

Contributor

alk commented Aug 23, 2015

Any luck here with the porting effort?

Reported by chappedm on 2012-04-21 18:28:24

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
No progress yet.

Reported by driodeiros on 2012-04-21 22:10:50

Contributor

alk commented Aug 23, 2015

No progress yet.

Reported by driodeiros on 2012-04-21 22:10:50

@alk

This comment has been minimized.

Show comment
Hide comment
@alk

alk Aug 23, 2015

Contributor
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>


Reported by psycharo on 2013-10-17 13:55:49

Contributor

alk commented Aug 23, 2015

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>


Reported by psycharo on 2013-10-17 13:55:49

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment