Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

!heap -p -a backtrace and gdb

69 views
Skip to first unread message

loren...@yahoo.com

unread,
Dec 5, 2007, 7:12:12 PM12/5/07
to
Hi,

I'm chasing a memory leak in an Obj-C program compiled with gcc, so I
tried combining windbg and gdb: I tracked down the offending blocks
and with +ust have been able to get a call trace for the allocations
which all look along these lines:

0:027> !heap -p -a 0adf5828
address 0adf5828 found in
_HEAP @ 3e0000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0adf5820 0023 0000 [07] 0adf5828 00100 - (busy)
Trace: 31bb
7c96d6dc ntdll!RtlDebugAllocateHeap+0x000000e1
7c949d18 ntdll!RtlAllocateHeapSlowly+0x00000044
7c91b298 ntdll!RtlAllocateHeap+0x00000e64
77c2c3c9 msvcrt!_heap_alloc+0x000000e0
77c2c3e7 msvcrt!_nh_malloc+0x00000013
77c2c42e msvcrt!malloc+0x00000027
6db48ec3 libobjc!objc_malloc+0x00000013
6db45733 libobjc!_objc_add_class_to_hash+0x00000143
6db48699 libobjc!_objc_exec_class+0x00000169
c78962 MyApp+0x00878962
121f007 MyApp+0x00e1f007
69f52b MyApp+0x0029f52b
40120c MyApp+0x0000120c
401253 MyApp+0x00001253
7c816fd7 kernel32!BaseProcessStart+0x00000023

Now I need to decode MyApp part of the backtrace. So I hoped that
attaching with gdb I would be able to get the symbolic backtrace using
the addresses supplied by wingdb, but - alas - all MyApp entries
translate to what seems to be random garbage to me:

(gdb) info br
Num Type Disp Enb Address What
2 breakpoint keep y 0x0069f52b in main at MyApp_main.m:152
3 breakpoint keep y 0x0121f007 <__do_global_ctors+55>
4 breakpoint keep y 0x00c78962 in global constructors keyed to
MyOther.bproj_MyLink.m_00000000_48D79E6E at MyOther.bproj/MyLink.m:17
5 breakpoint keep y 0x6db48699 in __objc_exec_class at init.c:
542
6 breakpoint keep y 0x6db45733 in __objc_add_class_to_hash
at class.c:189
7 breakpoint keep y 0x6db48ec3 in objc_malloc at misc.c:90

Nonsense backtrace for MyApp part to me... or I cannot interpret it.
And It looks like there is a bunch of frames missing - there is way
too few frames in MyApp to any place it could allocate memory from.

...I would leave this alone if I did not know that for breakpoints
this approach always works - addresses I see in wingdb accurately
translate to symbolic trace... So what is wrong with allocation
traces?

Any ideas anyone please?

David Welch

unread,
Dec 5, 2007, 7:33:28 PM12/5/07
to
loren...@yahoo.com wrote:
> Hi,
>
> I'm chasing a memory leak in an Obj-C program compiled with gcc, so I
> tried combining windbg and gdb: I tracked down the offending blocks
> and with +ust have been able to get a call trace for the allocations
> which all look along these lines:
[...]
>
Did you compile your program with frame pointer optimization
(-fomit-frame-pointer or -O)? That might cause windbg to show the wrong
backtrace.

Kalle Olavi Niemitalo

unread,
Dec 5, 2007, 11:45:23 PM12/5/07
to
loren...@yahoo.com writes:

> (gdb) info br
> Num Type Disp Enb Address What
> 2 breakpoint keep y 0x0069f52b in main at MyApp_main.m:152
> 3 breakpoint keep y 0x0121f007 <__do_global_ctors+55>
> 4 breakpoint keep y 0x00c78962 in global constructors keyed to
> MyOther.bproj_MyLink.m_00000000_48D79E6E at MyOther.bproj/MyLink.m:17
> 5 breakpoint keep y 0x6db48699 in __objc_exec_class at init.c:
> 542
> 6 breakpoint keep y 0x6db45733 in __objc_add_class_to_hash
> at class.c:189
> 7 breakpoint keep y 0x6db48ec3 in objc_malloc at misc.c:90
>
> Nonsense backtrace for MyApp part to me... or I cannot interpret it.
> And It looks like there is a bunch of frames missing - there is way
> too few frames in MyApp to any place it could allocate memory from.

Have you looked at the disassembly? GCC could very well have
generated a call from main to __do_global_ctors, even if no such
thing appears in your source code. In gcc-4.2.1/src/libobjc/init.c,
there is a comment above the definition of __objc_exec_class:

/* This function is called by constructor functions generated for each
module compiled. (_GLOBAL_$I$...) The purpose of this function is
to gather the module pointers so that they may be processed by the
initialization routines as soon as possible. */

__objc_add_class_to_hash deals with a hash table that maps
strings to Objective-C class objects. There does not seem to be
any way to remove classes from the hash table (perhaps partially
because class_table_get_safe reads the table without locking;
this may mean it is never safe to unload ObjC DLLs), but the
amount of memory allocated is constant per class, so I think you
should just ignore the leaks that have __objc_add_class_to_hash
in their call stacks.

loren...@yahoo.com

unread,
Dec 7, 2007, 4:22:17 PM12/7/07
to
On Dec 5, 7:33 pm, David Welch <we...@localhost.localdomain.invalid>
wrote:

[...]
> Did you compile your program with frame pointer optimization
> (-fomit-frame-pointer or -O)? That might cause windbg to show the wrong
> backtrace.

Yes, the app is compiled with -O3 I believe. I do not have the option
of debugging a non-optimized version however

On Dec 5, 11:45 pm, Kalle Olavi Niemitalo <k...@iki.fi> wrote:
[...]


> you should just ignore the leaks that have __objc_add_class_to_hash
> in their call stacks.

I believe the trace is just not correct. I have thousands of these
guys:
0:027> !heap -stat -h 003f0000
heap @ 003f0000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
100 b3071 - b307100 (27.49)
5a0 11ef3 - 64e16e0 (15.49)
800000 a - 5000000 (12.28)
...
And a lot of them have this same trace, in fact all go thru this:


3 breakpoint keep y 0x0121f007 <__do_global_ctors+55>

I can't believe they all relate to class object inits (btw I looked at
the bin dump of these guys and they are not NSObjects). It just looks
as a wrong backtrace to me. Sigh. I guess I have to find a different
approach here.

Thanks for your responses anyway.

Avi Cohen Stuart

unread,
Dec 10, 2007, 4:18:49 AM12/10/07
to
Hi,

Maybe for your information: the _do_global_ctor() is a function that is
called from _start() and does do the initialization of global constructors
in C++ when using g++.
Apprerantly something goes wrong when a global constructor is invoked.

Avi.

<loren...@yahoo.com> wrote in message
news:30d85c39-e282-4785...@s8g2000prg.googlegroups.com...

loren...@yahoo.com

unread,
Dec 10, 2007, 1:52:24 PM12/10/07
to
I would say the trace reported by windbg is just completely off.

I've idenified the nature of these 0x100-byte objects, and any place
they could be allocated from within MyApp would be at least 10-15
frames deep (but I still don't know which spot leaks exactly). Windgb
reports 5 frames within MyApp here... and 5 nonsense frames. I believe
they are just not correct at all, have nothing to do with the actual
allocation spot.

Not sure if this can be fixed somehow... maybe by increasing the
allocation database size? Anyone knows if I can just enable user-stack-
trace collection for objects of particular size?

Ivan Brugiolo [MSFT]

unread,
Dec 10, 2007, 2:52:59 PM12/10/07
to
As it has been reported several times in this forum,
the most likely source of the poor quality of the stack trace
is the fact that the functions in the stack do use FPO optimizations.

I'm not sure how to force the compiler to not generate
FPO optimized frames, but, in case of desperations, there are
tricks, such as calling `_alloca(sizeof(size_t))` that normally forces
FPO-less frames.

--

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


<loren...@yahoo.com> wrote in message
news:56919e79-f871-4995...@d27g2000prf.googlegroups.com...

loren...@yahoo.com

unread,
Dec 11, 2007, 2:43:24 PM12/11/07
to
On Dec 10, 2:52 pm, "Ivan Brugiolo [MSFT]"

<ivanb...@online.microsoft.com> wrote:
> As it has been reported several times in this forum,
> the most likely source of the poor quality of the stack trace
> is the fact that the functions in the stack do use FPO optimizations.

Just to make sure I rebuilt the app without optimizations - and still
the same story: call stack does not appear to be valid

Ivan Brugiolo [MSFT]

unread,
Dec 11, 2007, 3:26:59 PM12/11/07
to
I'm not sure how the concept FPO optimization maps to
the several `/Ox` flags of the compiler of your choice.
Just to make sure we speak about the same thing:
each and every function must have a prologue like:

81a5ac60 55 push ebp
81a5ac61 8bec mov ebp,esp

If this is not satisfied, please try to create large
on-the-stack volatile variables, via _alloca(), for example.

--

--
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of any included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm


<loren...@yahoo.com> wrote in message
news:70518c14-ceba-4fdd...@b40g2000prf.googlegroups.com...

Avi Cohen Stuart

unread,
Dec 12, 2007, 4:11:43 AM12/12/07
to
After reading this thread I'm wondering as you are using gcc where MyApp is
your code which doesn't show a stack trace and the libobjc which is also
from gcc does show a stack trace.
Maybe you need to dig into the gcc source code and try to figure out with
flags are used to compile the libobjc.
From that point on you should be able to find out which flags you need to
add to the gcc command line that allows you to show a stack trace from your
Obj-C source. I also don't know whether Obj-C does insert FP into its
assembled code.
Another option to find your memory leak is to use valgrind.

Avi.

<loren...@yahoo.com> wrote in message
news:a6161f9e-fb3f-4ca5...@l16g2000hsf.googlegroups.com...

Kalle Olavi Niemitalo

unread,
Dec 15, 2007, 2:40:00 PM12/15/07
to
"Ivan Brugiolo [MSFT]" <ivan...@online.microsoft.com> writes:

> Just to make sure we speak about the same thing:
> each and every function must have a prologue like:
>
> 81a5ac60 55 push ebp
> 81a5ac61 8bec mov ebp,esp

gcc -fno-omit-frame-pointer will generate that or equivalent.

0 new messages