> I wouldn't consider that a sufficient test. John Muth wrote a great article
> on a technique to detect memory leaks:
>
> http://www.cdpubs.com/hhsys/archives/62/07muth.pdf
>
> The idea is to intercept MemPtrNew and MemPtrFree. Each time you're asked
> to allocate new memory through MemPtrNew, you allocate slightly more bytes
> than requested. Then you pad a known pattern of bytes to the beginning and
> end of the pointer you return (that only you know about), and store the
> pointer you've returned in a linked list. The caller never knows about
> this.
>
> On MemPtrFree, you find the pointer in your linked list, and check to make
> sure your known pattern is still intact at the beginning and end of the
> memory area, and remove the ptr from the linked list. If the known pattern
> has been altered, that indicates that someone wrote beyond the bounds of the
> pointer (bad!). Also if the app is terminated and there are still entries
> in your linked list, that means someone failed to deallocate a pointer
> altogether.
>
> Though personally I would just use SysSetTrapAddress( sysMemPtrNewTrap,
> MyMemPtrNew ) to put a wrapper on MemPtrNew, and similarly for MemPtrFree.
> That way you don't have to go through and change all your code to call
> CLMemPtrNew, as the article suggests. Just be sure to reset the device when
> you're done testing. Quick and dirty.
Correct me if I'm wrong, but you can't just put a wrapper on the traps, at
least not wrappers like the one John wrote about because the traps don't
have access to globals. You will need to come up with another mech of
getting access to your globals (like maybe using a feature or DB, though
they are both pretty slow, and you don't know what memory calls they might
be using behind your back).
The other thing you can do, with similar effectiveness (ie not complete
tracking of memory) is create an include file with simple #defines so you
don't have to rename MemPtrNew to CLMemPtrNew. When not debugging, don't
include the include file and the real MemPtrNew() will be called.
For example, taking John's stuff:
#define MemPtrNew(sz) CLMemPtrNew(sz, __FILE__, __LINE__)
Note though, in these situations, it's really easy to get deceiving
information at the end of the application run. Reason being is that you
are only trapping memory calls that you make, and not any calls the system
makes for you. This may be considered better than nothing, but sometimes
it can be more confusing that worth it. Forms get really messy...
I've been playing around with the wrapper concept along with patching the
traps and have the basic memory traps handled (most of Mem* and Str*)
with a mech similar to John's. A pain in the butt compared to similar
functionality under unix (malloc, calloc, realloc, strdup is pretty much
most of what you need :)
This works better than the method above because here you are catching ALL
MemPtrNew() calls from the second you application starts. But it's still
not foolproof. For example, the OS is running in the background as another
thread, and will possible call Mem*() functions for it's own use, possibly
without the matching Mem*() function happening during your execution. This
type of issue also happens when dealing with things like resources. Not
unworkable issues, just more complex..
I started writing this because I really miss my unix tools like Dmalloc
and Dbmalloc. Knowing you have a memory leak is great, but even better is
catching a write to a bad ptr BEFORE it blows up the emulator :)
> As far as knowing WHERE the leak occurs, just put an ErrNonFatalDisplayIf()
> in your MemPtrFree routine when you sense something bad has occured. Then
> debug into the code and see which pointer caused the problem, and you should
> be able to take it from there. If you need more proactive debugging, maybe
> __FILE__ and __LINE__ are the right thing for you (see the article).
What I've done is tracked each allocation by it's __FILE__ and __LINE__ (I
think John was doing this too). Once I have that information, at any time
(especially during exit) I can iterate through my list of un-free'd ptrs
and do something with them (like display a dialog of them). I've also
found it useful to include a sequence number to the allocation.
Little bit more information then maybe be most want to know; I'm just
looking for 'kindered' souls hacking on this type of stuff..
-Jason