Up to: Mika Raento's Symbian Programming pages
Symbian Programming - Debugging memory leaks
The best way to debug memory leaks on 3rd edition is to use Symbian's
HookLogger tool as it allows you to dump the callstack for the leaked
allocation after you've seen the panic.
If you do have a repeatable panic address and hooklogger is not working for
you, you can override the default allocator and set a breakpoint in your own
code. See An
example custom allocator.
If you fail to free memory in an application running
on the emulator, the application framework will raise
a panic on exit. The panic tells you which memory cell
wasn't freed, but translating this into an allocation
takes a bit more work. The steps here are based on
Knowledge base article FAQ-0488.
The easier method
A somewhat easier way than the one detailed below is
- Note the hexadecimal address you get
with the ALLOC panic.
- Put a breakpoint somewhere in your app
before the memory gets allocated
(this might require some guessing).
- After hitting this breakpoint, add
a data breakpoint via Edit|Breakpoints|Data
and write 0x<<Panic address> in the
'Enter expression to be evaluated' box and
'4' in the 'Enter number of elements...' box.
- If you get an 'cannot set breakpoint' error
that memory region is not in use yet. Move your
original breakpoint further down your application
and try again.
- Now the program should stop when you allocate
the leaked memory, but it may stop before as well
if the memory gets reused. In that case just continue
until you hit the actual allocation.
The more tedious method
So you got your Panic ALLOC. After the panic
you get two numbers (the second one is 0). These are printed
in a panic dialog on the emulator, as well as in the debug
message pane in VC++. The first number is the address of
the leaked memory cell. What we want to do is find where
the memory was allocated.
Memory allocations happen in User::Alloc. We want
to put a breakpoint at the end of the function to see
when the offending cell is allocated. This isn't trivial,
since there are no debug symbols or code for the library.
What you have to do is:
- Find the exported function ordinal in EUSER.LIB
by running dumpbin /exports EUSER.LIB in
and looking for the User::Alloc(int). The first
number in the output row is the ordinal. For my
Series 60 SDK 1.0 this is 345.
- Find the function offset in the EUSER.DLL
by running dumpbin /exports EUSER.DLL and
looking for the ordinal you found in the previous step
(342). For me this gives offset 0000109B.
- In VC++ start the emulator (don't start your app yet).
- Go to Debug|Modules and look up the address EUSER.DLL
is loaded at (for me 0x60000000.
- Add the offset you got at step 2 to the load address,
I get 6000109B. Put a breakpoint there and start your
- Switch to the emulator and start your app, it should stop at the breakpoint.
Follow the disassembly from the initial jmp. Now
you are at the actually function (they seem to use incremental
linking). In my dll, this is at 0x6002D80B.
- Find the next ret statement beginning from
the point you are at. Set a breakpoint there. For
me this is at 0x60033ACD.
- Go to Edit|Breakpoints. Remove the first breakpoint you
set, and add the condition (EAX==<YOUR ALLOC PANIC ADDRESS>)
to the second one.
Now continue your application, and it should break at the point
where you are allocating the cell.
If you think the steps 1--5 are too complicated, you can find
the function address in another way as well:
- Put a call to User::Alloc() in your code.
- Put a breakpoint on that line
- Hit the breakpoint, step into the function once
(now you are in the link jump table in your app) and
twice (now you are at the EUSER.DLL initial
- Continue from step 6 above
Mika Raento, mikie(at)iki.fi