niuys/gperftools

heap-checker-death_unittest.sh fails in version 1.5 on linux

GoogleCodeExporter opened this issue · 27 comments

heap-checker-death_unittest.sh fails for me. I'm on linux 2.6.33.2, gcc 
4.4.3 and a x86_64-pc-linux-gnu. Here's what happens:


pipping@bogus ~/Downloads/google-perftools-1.5 $ make check TESTS=heap-
checker-
death_unittest.sh 
rm -f debugallocation_test.sh
cp -p ./src/tests/debugallocation_test.sh debugallocation_test.sh
rm -f sampling_test.sh
cp -p ./src/tests/sampling_test.sh sampling_test.sh
rm -f heap-profiler_unittest.sh
cp -p ./src/tests/heap-profiler_unittest.sh heap-profiler_unittest.sh
rm -f heap-checker_unittest.sh
cp -p ./src/tests/heap-checker_unittest.sh heap-checker_unittest.sh
rm -f heap-checker-death_unittest.sh
cp -p ./src/tests/heap-checker-death_unittest.sh heap-checker-
death_unittest.sh
rm -f sampling_debug_test.sh
cp -p ./src/tests/sampling_test.sh sampling_debug_test.sh
rm -f heap-profiler_debug_unittest.sh
cp -p ./src/tests/heap-profiler_unittest.sh heap-profiler_debug_unittest.sh
rm -f heap-checker_debug_unittest.sh
cp -p ./src/tests/heap-checker_unittest.sh heap-checker_debug_unittest.sh
rm -f profiler_unittest.sh
cp -p ./src/tests/profiler_unittest.sh profiler_unittest.sh
for la in libtcmalloc_minimal.la libtcmalloc_minimal_debug.la 
libtcmalloc.la 
libtcmalloc_debug.la libtcmalloc_and_profiler.la; do lib=".libs/`basename 
$la 
.la`.a"; [ ! -f "$lib" ] || objcopy -W malloc -W free -W realloc -W calloc 
-W cfree -
W memalign -W posix_memalign -W valloc -W pvalloc -W malloc_stats -W 
mallopt -W 
mallinfo -W _Znwm -W _ZnwmRKSt9nothrow_t -W _Znam -W _ZnamRKSt9nothrow_t -W 
_ZdlPv -W 
_ZdaPv -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t 
-W __ZdlPv 
-W __ZdaPv "$lib"; done
make  pprof_unittest
make[1]: Entering directory `/home/pipping/Downloads/google-perftools-1.5'
./src/pprof -test
AddressAdd 32-bit tests: 5 passes, 0 failures
AddressAdd 64-bit tests: 10 passes, 0 failures
AddressSub 32-bit tests: 5 passes, 0 failures
AddressSub 64-bit tests: 10 passes, 0 failures
AddressInc 32-bit tests: 5 passes, 0 failures
AddressInc 64-bit tests: 10 passes, 0 failures
PASS
make[1]: Leaving directory `/home/pipping/Downloads/google-perftools-1.5'
make  check-TESTS
make[1]: Entering directory `/home/pipping/Downloads/google-perftools-1.5'
rm -f heap-checker-death_unittest.sh
cp -p ./src/tests/heap-checker-death_unittest.sh heap-checker-
death_unittest.sh
Testing ./heap-checker_unittest with HEAPCHECK= ... PASS
Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_NO_THREADS=1 ... 
PASS

Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 ... PASS
Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 
HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 ... PASS
Testing ./heap-checker_unittest with HEAPCHECK= 
HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=1 ... PASS
Testing ./heap-checker_unittest with HEAPCHECK= 
HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=2 ... PASS
Testing ./heap-checker_unittest with HEAPCHECK= 
HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=-2 ... PASS
Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECKER_TEST_NO_THREADS=1 ... PASS
Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 
HEAP_CHECKER_TEST_NO_THREADS=1 ... PASS
Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECK_TEST_NO_THREADS=1 ... FAIL
Output did not match 'MakeALeak'
Output from failed run:

---
WARNING: Perftools heap leak checker is active -- Performance may suffer

Adding pthread-specifics for thread 47509864235200 pid 17933
Creating extra thread 1
Creating extra thread 2
A new HeapBusyThread 0
Adding pthread-specifics for thread 47509870302992 pid 17933

Creating extra thread 3
A new HeapBusyThread 1
Adding pthread-specifics for thread 47509872404240 pid 17933
Creating extra thread 4
Creating extra thread 5
Creating extra thread 6
A new HeapBusyThread 2
Adding pthread-specifics for thread 47509874505488 pid 17933
Creating extra thread 7
A new HeapBusyThread 4
Adding pthread-specifics for thread 47509878712080 pid 17933
Creating extra thread 8
A new HeapBusyThread 6
Adding pthread-specifics for thread 47509882918672 pid 17933
A new HeapBusyThread 3
Adding pthread-specifics for thread 47509876606736 pid 17933
A new HeapBusyThread 5
Adding pthread-specifics for thread 47509880813328 pid 
Creating extra thread 9
A new HeapBusyThread 7
Adding pthread-specifics for thread 47509885019920 pid 1793317933
Creating extra thread 10
Creating extra thread 11
Creating extra thread 12
A new HeapBusyThread 10
Adding pthread-specifics for thread 47509891327760 pid 17933
A new HeapBusyThread 9
Adding pthread-specifics for thread 47509889222416 pid 17933
A new HeapBusyThread 8
Adding pthread-specifics for thread 47509887121168 pid 17933
Creating extra thread 13
A new HeapBusyThread 11
Adding pthread-specifics for thread 47509893433104 pid 17933
Creating extra thread 14
Creating extra thread 15
A new HeapBusyThread 
Creating extra thread 16
A new HeapBusyThread 13
Adding pthread-specifics for thread 47509897635600 pid 17933
Creating extra thread 1712
Adding pthread-specifics for thread 47509895534352 pid 17933

A new HeapBusyThread 14
Adding pthread-specifics for thread 47509899736848 pid 17933
A new HeapBusyThread 15
Adding pthread-specifics for thread 47509901838096 pid 17933
A new HeapBusyThread 16
Adding pthread-specifics for thread 47509903943440 pid 17933
Adding pthread-specifics for thread 47509864235200 pid 17933
In main(): heap_check=strict
No leaks found for check "_main_" (but no 100% guarantee that there aren't 
any): 
found 1305 reachable heap objects of 145527 bytes

Leaking : 0xf2493bcb ^ 0xf03a5f7b
PASS
Leak check _main_ detected leaks of 40 bytes in 1 objects
The 1 largest leaks:
Leak of 40 bytes in 1 objects allocated from:
        @ 2b35bfa853bd operator new


If the preceding stack traces are not enough to find the leaks, try running 
THIS 
shell command:

pprof /home/pipping/Downloads/google-perftools-1.5/.libs/lt-heap-
checker_unittest 
"/tmp/lt-heap-checker_unittest.17933._main_-end.heap" --inuse_objects --
lines --
heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --gv

If you are still puzzled about why the leaks are there, try rerunning this 
program 
with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with 
HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with 
TCMALLOC_MAX_FREE_QUEUE_SIZE of few h
Exiting with error code (instead of crashing) because of whole-program 
memory leaks

---
FAIL: heap-checker-death_unittest.sh
======================================
1 of 1 tests failed
Please report to opensource@google.com
======================================
make[1]: *** [check-TESTS] Error 1
make[1]: Leaving directory `/home/pipping/Downloads/google-perftools-1.5'
make: *** [check-am] Error 2

I'm attaching my config.log

Original issue reported on code.google.com by pipping....@gmail.com on 26 Apr 2010 at 11:00

Attachments:

I can reproduce this using gcc 4.5 -- I think it's an issue with the newer 
gcc's 
(we've been having several).

The proximate problem here is we're not getting a complete stacktrace: it shows 
the 
operator-new call but not anything before that.  Hence the death test is 
failing 
because it's not seeing the stacktrace it expects.  I'll see if I can figure 
out why.

Out of curiousity, can you try building with optimization off (do "./configure 
... 
CXXFLAGS=-g")?  Let me know if the test passes in that case.

Original comment by csilv...@gmail.com on 27 Apr 2010 at 4:02

  • Changed state: Accepted
  • Added labels: Priority-Medium, Type-Defect
It's definitely not a problem with gcc 4.5 because as I mentioned in my post, I 
used 
gcc 4.4.3 for this test.

Original comment by pipping....@gmail.com on 27 Apr 2010 at 5:59

CFLAGS=-g3 doesn't exactly help. Now a whole lot more fails.

FAIL: sampling_test.sh
FAIL: heap-profiler_unittest.sh
FAIL: heap-checker_unittest.sh
FAIL: heap-checker-death_unittest.sh
FAIL: sampling_debug_test.sh
FAIL: heap-profiler_debug_unittest.sh
FAIL: heap-checker_debug_unittest.sh

Original comment by pipping....@gmail.com on 27 Apr 2010 at 6:02

Also with -g3:

$ ./heap-checker-death_unittest.sh
Testing ./heap-checker_unittest with HEAPCHECK= ... PASS
Testing ./heap-checker_unittest with HEAP_CHECKER_TEST_NO_THREADS=1 ... FAIL
Wrong exit code: expected: '0'; actual: 134
Output did not match '^PASS$'
Output from failed run:
---
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
WARNING: Perftools heap leak checker is active -- Performance may suffer
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace

Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace

Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace
Hooked allocator frame not found, returning empty trace


0x0 does not seem to point into code of function Mmapper at 0x402df0! Stack 
frame 
collection must be off in MemoryRegionMap!---

Original comment by pipping....@gmail.com on 27 Apr 2010 at 6:04

perftools uses CXXFLAGS, not CFLAGS, so if it was really CFLAGS=-g3, it wasn't 
really 
changing anything.

When I run with CXXFLAGS=-g3 on gcc 4.4.3, I get just the one failure you 
reported 
first, in the death test.  So it looks like whatever the problem is here, it 
doesn't 
have to do with optimization.

I dug into this a bit tonight, and it looks like the problem is that the new 
glibc 
libstdc++ that comes with gcc 4.4.3, is not compiled with support for frame 
pointers 
on x86_64 (it looks like you configured with --enable-frame-pointers, like I 
do).  As 
a result, we can't get a good stack trace.  Here's an example of a 'real' stack 
trace 
we should be generating, which is what gdb returns:
---
(gdb) bt
#0  GetStackTrace (result=0x7fffffffdef0, max_depth=42, skip_count=0) at src/st\
acktrace_x86-inl.h:319
#1  0x00002aaaab02b130 in MallocHook_GetCallerStackTrace (result=0x7fffffffe0a0\
, max_depth=32, skip_count=3) at src/malloc_hook.cc:324
#2  0x00002aaaab02f69b in MallocHook::GetCallerStackTrace (result=0x7fffffffe0a\
0, max_depth=32, skip_count=3) at ./src/google/malloc_hook.h:192
#3  0x00002aaaab02df6a in HeapProfileTable::RecordAlloc (this=0x2aaaabaef020, p\
tr=0x69d000, bytes=77, skip_count=0) at src/heap-profile-table.cc:196
#4  0x00002aaaab0145e8 in NewHook (ptr=0x69d000, size=77) at src/heap-checker.c\
c:547
#5  0x00002aaaab0114c6 in MallocHook::InvokeNewHook (p=0x69d000, s=77) at src/m\
alloc_hook-inl.h:98
#6  0x00002aaaab040bce in tc_malloc (size=77) at src/tcmalloc.cc:1336
#7  0x00002aaaaad904fd in operator new(unsigned long) () from /usr/crosstool/v1\
4-nightly-latest/gcc-4.4.3-glibc-2.11.1-grte/x86/bin/../lib/gcc/x86_64-unknown-\
linux-gnu/4.4.3/../../../../lib64/libstdc++.so.6
#8  0x00002aaaaad90619 in operator new[](unsigned long) () from /usr/crosstool/\
v14-nightly-latest/gcc-4.4.3-glibc-2.11.1-grte/x86/bin/../lib/gcc/x86_64-unknow\
n-linux-gnu/4.4.3/../../../../lib64/libstdc++.so.6
#9  0x0000000000402d5b in operator new[] (size=77) at src/tests/heap-checker_un\
ittest.cc:256
#10 0x0000000000404cb1 in TestLibCAllocate () at src/tests/heap-checker_unittes\
t.cc:836
#11 0x0000000000406ce9 in main (argc=1, argv=0x7fffffffe5e8) at src/tests/heap-\
checker_unittest.cc:1370
---

but our stacktracer, which follows the stack pointer, gets as far as operator 
new 
(frame 7).  Beyond that, the sp points to NULL.

I haven't had time to look into this more, to see if that means we'll never get 
any 
good stack traces with gcc 4.4.3 for calls to new.  libunwind still isn't ready 
for 
prime time yet, so we've been depending on compiling with 
--enable-frame-pointers to 
do something useful.  I hope that hasn't stopped being the case.

To test this theory, you could see if you have a 'debug' version of libstdc++ 
around 
(in /usr/lib/debug), and try linking against that instead of the normal 
libstdc++.  
I'm not exactly sure how to do that -- you may need to do the c++ linking by 
hand.  
Then test if the unittests pass with that mode.

Original comment by csilv...@gmail.com on 28 Apr 2010 at 12:57

Sorry, I don't have a debug version of libstdc++. iirc it refuses to be built 
with -
O0, too.

You're right, I set CFLAGS when I meant to set CXXFLAGS in the above. I can't 
reproduce that problem with all the additional failing tests either. Weird.

Original comment by pipping....@gmail.com on 28 Apr 2010 at 2:15

I looked into this some more tonight, with some help from a few compiler 
experts at 
google, and we discovered the problem (I think).  As I had figured out earlier, 
the 
trouble is with the operator new from libstdc++.  But we should never be 
calling that 
operator new -- we should be using the operator new from libtcmalloc!

The reason you're getting the wrong operator new is because libtcmalloc is 
coming 
after libstdc++ on the commandline for you at link time.  You can look at your 
make 
output to verify.  If you do
  make heap-checker_unittest
the last line will be something like
  g++ -Wall [...] heap_checker_unittest-heap-checker_unittest.o  ./.libs/liblogging.a 
<something>/libstdc++.so  ./.libs/libtcmalloc.so [...]

Maybe just attach the entire output of a clean 'make' run.

I have no idea why this happens.  I guess I'll need to talk to a libtool expert 
next...

Original comment by csilv...@gmail.com on 6 May 2010 at 7:17

Oh, a workaround for the unittest, at leatt, would be to re-link the program 
manually, 
copying the link line but moving the libstdc++ to the end.  Then 'make check' 
should 
pass.

This problem shouldn't affect you in 'real life', where presumably you're just 
linking 
in tcmalloc by running g++ ... -ltcmalloc, rather than using libtool.

Original comment by csilv...@gmail.com on 6 May 2010 at 7:18

Ok, the local libtool expert just got back to me, with this quote:
---

libtool must die!

Yes, it often does screwy things like this, and (AFAICT) there is no
way to stop it.

It basically constructs link lines that *almost* work, but aren't
correct or what you actually want :-(
---

Not exactly inspiring as to being fixable.  But let's look at your specific 
make 
output and see what we can see.  You may also want to include your libtool 
script.

Original comment by csilv...@gmail.com on 6 May 2010 at 7:22

> Maybe just attach the entire output of a clean 'make' run.


pipping@bogus ~/Downloads/google-perftools-1.5 $ ./configure 
--enable-frame-pointers > 
configure.log
pipping@bogus ~/Downloads/google-perftools-1.5 $ make > make.log 2>&1
pipping@bogus ~/Downloads/google-perftools-1.5 $ 

Original comment by pipping....@gmail.com on 6 May 2010 at 5:33

Attachments:

The relevant bits:


pipping@bogus ~/Downloads/google-perftools-1.5 $ rm -f 
.libs/libtcmalloc.so.0.0.0 
.libs/heap-checker_unittest libtcmalloc.la heap-checker_unittest
pipping@bogus ~/Downloads/google-perftools-1.5 $ make libtcmalloc.la heap-
checker_unittest
/bin/sh ./libtool --tag=CXX --mode=link g++ -Wall -Wwrite-strings -Woverloaded-
virtual -Wno-sign-compare -fno-omit-frame-pointer  -g -O2 -no-undefined   -o 
libtcmalloc.la -rpath /usr/local/lib -pthread libtcmalloc_la-tcmalloc.lo    
thread_lister.lo libtcmalloc_la-linuxthreads.lo libtcmalloc_la-heap-checker.lo 
libtcmalloc_la-heap-checker-bcad.lo  libtcmalloc_internal.la 
rm -fr  .libs/libtcmalloc.a .libs/libtcmalloc.la .libs/libtcmalloc.lai 
.libs/libtcmalloc.so .libs/libtcmalloc.so.0
g++ -shared -nostdlib /usr/lib64/gcc/x86_64-pc-linux-
gnu/4.4.4/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-pc-linux-
gnu/4.4.4/crtbeginS.o  .libs/libtcmalloc_la-tcmalloc.o .libs/thread_lister.o 
.libs/libtcmalloc_la-linuxthreads.o .libs/libtcmalloc_la-heap-checker.o 
.libs/libtcmalloc_la-heap-checker-bcad.o -Wl,--whole-archive 
./.libs/libtcmalloc_internal.a -Wl,--no-whole-archive  -Wl,--rpath -
Wl,/usr/lib64/../lib64 -Wl,--rpath -Wl,/usr/lib64/../lib64 
-L/usr/lib64/gcc/x86_64-
pc-linux-gnu/4.4.4 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4 
-L/usr/lib64/gcc/x86_64-
pc-linux-gnu/4.4.4/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -
L/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../x86_64-pc-linux-gnu/lib -
L/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../.. 
/usr/lib64/../lib64/libstdc++.so -
lm -lc -lgcc_s /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/crtendS.o 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../lib64/crtn.o  -pthread 
-Wl,-
soname -Wl,libtcmalloc.so.0 -o .libs/libtcmalloc.so.0.0.0
(cd .libs && rm -f libtcmalloc.so.0 && ln -s libtcmalloc.so.0.0.0 
libtcmalloc.so.0)
(cd .libs && rm -f libtcmalloc.so && ln -s libtcmalloc.so.0.0.0 libtcmalloc.so)
rm -fr .libs/libtcmalloc.lax
mkdir .libs/libtcmalloc.lax
rm -fr .libs/libtcmalloc.lax/libtcmalloc_internal.a
mkdir .libs/libtcmalloc.lax/libtcmalloc_internal.a
(cd .libs/libtcmalloc.lax/libtcmalloc_internal.a && ar x 
/home/pipping/Downloads/google-perftools-1.5/./.libs/libtcmalloc_internal.a)
ar cru .libs/libtcmalloc.a  libtcmalloc_la-tcmalloc.o thread_lister.o 
libtcmalloc_la-
linuxthreads.o libtcmalloc_la-heap-checker.o libtcmalloc_la-heap-checker-bcad.o 

.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-sampler.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-malloc_hook
.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-
central_freelist.o .libs/libtcmalloc.lax/libtcmalloc_internal.a/vdso_support.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-thread_cach
e.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-maybe_threa
ds.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-common.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/sysinfo.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/atomicops-internals-x86.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-raw_printer
.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-heap-profil
e-
table.o .libs/libtcmalloc.lax/libtcmalloc_internal.a/stacktrace_with_context.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-static_vars
.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-system-allo
c.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-heap-profil
er.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/stacktrace.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-
memory_region_map.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/dynamic_annotations.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-symbolize.o

.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-
stack_trace_table.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-
internal_logging.o .libs/libtcmalloc.lax/libtcmalloc_internal.a/logging.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/spinlock.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-
malloc_extension.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-span.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-page_heap.o

.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-memfs_mallo
c.o 
.libs/libtcmalloc.lax/libtcmalloc_internal.a/libtcmalloc_internal_la-
low_level_alloc.o 
ranlib .libs/libtcmalloc.a
rm -fr .libs/libtcmalloc.lax
creating libtcmalloc.la
(cd .libs && rm -f libtcmalloc.la && ln -s ../libtcmalloc.la libtcmalloc.la)
/bin/sh ./libtool --tag=CXX --mode=link g++ -Wall -Wwrite-strings -Woverloaded-
virtual -Wno-sign-compare -fno-omit-frame-pointer  -g -O2 -no-undefined   -o 
heap-
checker_unittest -g -pthread  heap_checker_unittest-heap-checker_unittest.o   
liblogging.la libtcmalloc.la 
g++ -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare 
-fno-omit-frame-
pointer -g -O2 -o .libs/heap-checker_unittest -g -pthread 
heap_checker_unittest-heap-
checker_unittest.o  ./.libs/liblogging.a /usr/lib64/../lib64/libstdc++.so 
./.libs/libtcmalloc.so  -Wl,--rpath -Wl,/usr/lib64/../lib64
creating heap-checker_unittest
pipping@bogus ~/Downloads/google-perftools-1.5 $ 

Original comment by pipping....@gmail.com on 6 May 2010 at 5:39

So what usually happens is

pipping@bogus ~/Downloads/google-perftools-1.5 $ g++ -shared -nostdlib 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../lib64/crti.o 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/crtbeginS.o  
.libs/libtcmalloc_la-tcmalloc.o 
.libs/thread_lister.o .libs/libtcmalloc_la-linuxthreads.o 
.libs/libtcmalloc_la-heap-
checker.o .libs/libtcmalloc_la-heap-checker-bcad.o -Wl,--whole-archive 
./.libs/libtcmalloc_internal.a -Wl,--no-whole-archive  -Wl,--rpath -
Wl,/usr/lib64/../lib64 -Wl,--rpath -Wl,/usr/lib64/../lib64 
-L/usr/lib64/gcc/x86_64-
pc-linux-gnu/4.4.4 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4 
-L/usr/lib64/gcc/x86_64-
pc-linux-gnu/4.4.4/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -
L/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../x86_64-pc-linux-gnu/lib -
L/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../.. 
/usr/lib64/../lib64/libstdc++.so -
lm -lc -lgcc_s /usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/crtendS.o 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../lib64/crtn.o  -pthread 
-Wl,-
soname -Wl,libtcmalloc.so.0 -o .libs/libtcmalloc.so.0.0.0
pipping@bogus ~/Downloads/google-perftools-1.5 $ g++ -Wall -Wwrite-strings -
Woverloaded-virtual -Wno-sign-compare -fno-omit-frame-pointer -g -O2 -o 
.libs/heap-
checker_unittest -g -pthread heap_checker_unittest-heap-checker_unittest.o  
./.libs/liblogging.a /usr/lib64/../lib64/libstdc++.so ./.libs/libtcmalloc.so  
-Wl,--
rpath -Wl,/usr/lib64/../lib64
pipping@bogus ~/Downloads/google-perftools-1.5 $

resulting in


pipping@bogus ~/Downloads/google-perftools-1.5 $ 
./heap-checker-death_unittest.sh 
>/dev/null ; echo $?
10
pipping@bogus ~/Downloads/google-perftools-1.5 $

Original comment by pipping....@gmail.com on 6 May 2010 at 5:41

I thought this should work now:

pipping@bogus ~/Downloads/google-perftools-1.5 $ g++ -shared -nostdlib 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../lib64/crti.o 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/crtbeginS.o  
.libs/libtcmalloc_la-tcmalloc.o 
.libs/thread_lister.o .libs/libtcmalloc_la-linuxthreads.o 
.libs/libtcmalloc_la-heap-
checker.o .libs/libtcmalloc_la-heap-checker-bcad.o -Wl,--whole-archive 
./.libs/libtcmalloc_internal.a -Wl,--no-whole-archive  -Wl,--rpath -
Wl,/usr/lib64/../lib64 -Wl,--rpath -Wl,/usr/lib64/../lib64 
-L/usr/lib64/gcc/x86_64-
pc-linux-gnu/4.4.4 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4 
-L/usr/lib64/gcc/x86_64-
pc-linux-gnu/4.4.4/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -
L/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../../../x86_64-pc-linux-gnu/lib -
L/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/../../..  -lm -lc -lgcc_s 
/usr/lib64/gcc/x86_64-pc-linux-gnu/4.4.4/crtendS.o 
/usr/lib64/gcc/x86_64-pc-linux-
gnu/4.4.4/../../../../lib64/crtn.o  -pthread -Wl,-soname -Wl,libtcmalloc.so.0 
-o 
.libs/libtcmalloc.so.0.0.0 /usr/lib64/../lib64/libstdc++.so
pipping@bogus ~/Downloads/google-perftools-1.5 $ g++ -Wall -Wwrite-strings -
Woverloaded-virtual -Wno-sign-compare -fno-omit-frame-pointer -g -O2 -o 
.libs/heap-
checker_unittest -g -pthread heap_checker_unittest-heap-checker_unittest.o  
./.libs/liblogging.a /usr/lib64/../lib64/libstdc++.so ./.libs/libtcmalloc.so  
-Wl,--
rpath -Wl,/usr/lib64/../lib64
pipping@bogus ~/Downloads/google-perftools-1.5 $

It doesn't, though:

pipping@bogus ~/Downloads/google-perftools-1.5 $ 
./heap-checker-death_unittest.sh 
>/dev/null ; echo $?
8
pipping@bogus ~/Downloads/google-perftools-1.5 $ 

Am I doing something wrong?

Original comment by pipping....@gmail.com on 6 May 2010 at 5:43

Ah, exactly as I suspected -- libtool is putting libstdc++ too early on the 
link 
line.  I have no idea why.

} $ g++ -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare 
-fno-omit-frame-
pointer -g -O2 -o .libs/heap-checker_unittest -g -pthread 
heap_checker_unittest-heap-
checker_unittest.o  ./.libs/liblogging.a /usr/lib64/../lib64/libstdc++.so 
./.libs/libtcmalloc.so  -Wl,--rpath -Wl,/usr/lib64/../lib64

You need to put libstdc++.so last, after libtcmalloc.so.

Also -- and this is getting into libtool magic that I'm not really very sure of 
-- 
this emits .libs/heap-chekcer_unittest, but you really need the binary to be 
.libs/lt-heap-checker_unittest.  I'm not sure if you can just rename the 
binary, or 
have to do some other magic.

I've verified the fix manually, like so:
---
env LD_LIBRARY_PATH=.libs HEAPCHECK=normal HEAP_CHECKER_TEST_TEST_LEAK=1 
HEAP_CHECK_TEST_NO_THREADS=1 ./.libs/heap-checker_unittest
---

If you get a full backtrace, then things are fixed.  If you only see 'operator 
new', 
they're still broken.

Original comment by csilv...@gmail.com on 6 May 2010 at 8:30

> You need to put libstdc++.so last, after libtcmalloc.so.

I did just that as you can see above. I don't understand the libtool parts, 
though.

> I've verified the fix manually, like so:

So you got it with gcc 4.4.x, too and it went away after reordering those 
libraries? 
if so, that's good enough for me, no need to try and explain to me what I'm 
doing 
wrong.

Original comment by pipping....@gmail.com on 7 May 2010 at 12:26

} > You need to put libstdc++.so last, after libtcmalloc.so.
} I did just that as you can see above. I don't understand the libtool parts, 
though.

You did for the first command (creating libtcmalloc.so), but not for the second 
(creating .libs/heap-chekcer_unittest).  That's the important one.

You can ignore the libtool parts, and just run your second g++ command again, 
this 
time putting libstdc++.so at the end.  Then run the 'env' command I mentioned 
below, 
and look at the stacktrace the unittest reports.  Hopefully it will be a full 
one 
now.

} So you got it with gcc 4.4.x, too and it went away after reordering those 
libraries? 

Yep, but if you can double-check it works for you, that would be great!  I'm 
pretty 
confident it will, though.

Original comment by csilv...@gmail.com on 7 May 2010 at 12:46

Either it doesn't work or your instructions are too vague (although I somewhat 
doubt 
it's the latter).

Would you mind ssh'ing into my box? Unfortunately I don't have a static IP here 
(and 
setting up a dynamic one would be a pain since i'm behind two routers and only 
the 
innermost is capable of that but would naturally transmit the wrong IP). So it 
could 
be kind of annoying since my IP changes every 24h. But still it might put an 
end to 
this mess.

Original comment by pipping....@gmail.com on 7 May 2010 at 1:52

I'm heading out right now, unfortunately, but can try again tomorrow.  Do you 
want to 
mail the IP and username to ssh in, next time the IP address changes (and 
password, if 
needed)?  Also, let me know what directory to look in.

Original comment by csilv...@gmail.com on 7 May 2010 at 1:57

I'd need to tell you the IP and you'd need to tell me your public ssh key 
(unless you 
really do want a password). I've set up a user names csilvers, extracted google-
perftools 1.5 into his home directory, run configure and make.

gcc-4.4, gcc-4.5 and clang are installed (they can be found in /usr/bin or 
PATH).

The problem is that I don't know your email address, you don't know mine, and 
neither 
one of use can find out what the other's address is without writing it down 
here in 
plain text, hm?

Original comment by pipping....@gmail.com on 7 May 2010 at 2:03

I can share my email no problem (I think it's on the front page of this google 
code
project anyway): csilvers@gmail.com.

Here's my public ssh key:

1024 37
14332733690391907636149913369182685113349225926297441979741118397397498947146366
90390116229376426821497705229536972979392091876873920539204158933423026228012128
09233503326665489399017189784369358459458822600533266629968302374994136243978009
934971322278956353455880937800295533590211333845812622635493057832533
csilvers

Original comment by csilv...@gmail.com on 7 May 2010 at 4:21

OK, thanks for the ssh access.  I got in and tried compiling with libstdc++ 
later in 
the linkline, and it worked fine -- I got the 'correct' stacktrace this time.  
So it 
looks like we understand the problem and how to fix it manually.  I'm still 
working on 
if it's possible to fix it automatically, in libtool.


Original comment by csilv...@gmail.com on 7 May 2010 at 6:29

Thanks a lot and sorry for all the hassle.

Original comment by pipping....@gmail.com on 7 May 2010 at 6:34

Sorry, one more question: can you attach your .libs/libtcmalloc.la file?

I'm still trying to figure out how to fix libtool so this problem won't happen 
to 
other folks.

Original comment by csilv...@gmail.com on 7 May 2010 at 10:50

I tracked down the problem in libtool, and figured out a workaround for the 
problem 
by reordering some libraries in Makefile.am.  So this will be fixed in the next 
release.

For anyone curious what the issue is:

The bug has to do when trying to combine
dependencies between libtool convenience libraries and 'normal'
libraries.  libtool treats convenience libraries and normal libraries
in separate passes, and therefore loses important dependency-graph
information if both of them depend on the same library (in this case,
libstdc++).

Here's a small Makefile.am that reproduces the problem:
---
lib_LTLIBRARIES = libdep.la libmain.la
noinst_LTLIBRARIES = libconv.la

libconv_la_SOURCES = test.c
libconv_la_LIBADD = libdep.la

libmain_la_SOURCES = test.c
libmain_la_LIBADD = libdep.la

libdep_la_SOURCES = test.c

noinst_PROGRAMS = main
main_SOURCES = testenv.c
main_LDADD = libconv.la libmain.la 
---
Along with this configure.ac:
---
AC_PREREQ(2.57)
AC_INIT(test, 1.0)
AC_CONFIG_SRCDIR(test.c)
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([dist-zip])

AC_PROG_CC
AC_PROG_LIBTOOL

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
---
You'll also need a trivial test.c, testenv.c, and all the random files
required by automake.  Also, libtool and ltmain.sh.

Once you have that, and run autoreconf + Make, libtool will generate
the following compile line:

gcc -g -O2 -o .libs/main testenv.o  ./.libs/libconv.a /var/tmp/.libs/libdep.so 
./.libs/libmain.so

I forget exactly which way the deps are supposed to go, but whichever
way it is this linkline isn't right: libconv depends on libdep and
comes before it, while libmain depends on libdep and comes after it.

Original comment by csilv...@gmail.com on 7 May 2010 at 11:37

  • Changed state: Started
Assuming this is still needed:

> Sorry, one more question: can you attach your .libs/libtcmalloc.la file?

If you mean ~/google-perftools-1.5/.libs/libtcmalloc.la from the home of your 
account, 
this is it:

Original comment by pipping....@gmail.com on 8 May 2010 at 1:47

Attachments:

Thanks, that's just what I needed.  It looks like I expected, with an explicit
dependency on libstdc++ but nothing else.  The fix I've submitted to the 
Makefile
should resolve this, in the next release.

Original comment by csilv...@gmail.com on 9 May 2010 at 10:24

This should be fixed in perftools 1.6, just released.

Original comment by csilv...@gmail.com on 5 Aug 2010 at 8:51

  • Changed state: Fixed