ETStackTraceRecorder documentation
ETStackTraceRecorder : NSObjectOverview
A stack trace recorder allows to snapshot the call stack symbols and inspect these snapshots later on.
You invoke -recordForObject: to snapshot the current call stack symbols and -recordedStackTracesForObject: to get all the call stack traces recorded until now.
A stack trace recorder is very handy to debug memory management issues. e.g. You can easily discover where an over-released object was allocated in a vein similar to malloc_history on Mac OS X.
Take note that +enableAllocationRecordingForClass: is only available on GNUstep and the example detailed below doesn't apply to Mac OS X where you must use malloc_history instead.
To get meaningfull backtrace on GNUstep, you must install the GNU bin utils (e.g. binutils-dev package on Ubuntu) and configure GNUstep Base with --enable-bfd.
Be aware that the resulting gnustep-base library will be GPL-licensed and transively all the code that links it will become GPL-licensed too.
Use Case Example
For a retain/release crash, note the instance class that got double-released, then add in main() or equivalent:
[[ETStackTraceRecorder sharedInstance] enableAllocationRecordingForClass: [MyClass class]];
To prevent the instance to be deallocated, set NSZombieEnabled to YES (e.g. export NSZombieEnabled YES in the shell). Finally compile and run the program in GDB and at crash time, type on the GDB prompt:
po [[ETStackTraceRecorder sharedInstance] recordedStackTracesForObject: instance] firstObject]
Where instance is the instance address or a
variable pointing on the instance. Then GDB prints
the stack trace which points back to the code that
allocated the instance.
You can also put a
breakpoint on -[NSZombie forwardInvocation:],
but take note that NSZombie doesn't respond to
-recordedStackTraces
(at least on GNUstep).
Thread Safety
ETStackTraceRecorder is thread-safe (not fully yet), multiple threads can invoke -recordForObject: .
Initialization
- + (id) sharedInstance
Returns the shared stack trace recorder.
Returns the shared stack trace recorder.
Object Allocation Recording
- - (void) enableAllocationRecordingForClass: (Class)aClass
Enables the recording of the stack trace every time +allocWithZone: is called on the given class.
Doesn't apply to subclasses. e.g. Using NSObject as argument won't trigger the allocation recording for every instances.
You must pass concrete subclasses to record class cluster allocations. e.g. GSDictionary for NSDictionary.For now, using this method on other recorders than the one returned by +sharedInstance is not supported.
To detect object allocations, the receiver sets up alloc/dealloc callbacks with GSSetDebugAllocationFunctions() . You cannot use these hooks in your code and at the same time record the allocation with ETStackTraceRecorder.
Enables the recording of the stack trace every time +allocWithZone: is called on the given class.
Doesn't apply to subclasses. e.g. Using NSObject as argument won't trigger the allocation recording for every instances.
You must pass concrete subclasses to record class cluster allocations. e.g. GSDictionary for NSDictionary.For now, using this method on other recorders than the one returned by +sharedInstance is not supported.
To detect object allocations, the receiver sets up alloc/dealloc callbacks with GSSetDebugAllocationFunctions() . You cannot use these hooks in your code and at the same time record the allocation with ETStackTraceRecorder.
- - (void) disableAllocationRecordingForClass: (Class)aClass
Disables the recording of the stack trace every time +allocWithZone: is called on the given class.
Doesn't apply subclasses. See -enableAllocationRecordingForClass: for more details.
Recording and Accessing Stack Traces
- - (void) recordForObject: (id)anObject
Records the call stack symbols in relation to the given object.
Records the call stack symbols in relation to the given object.
- - (NSArray *) recordedStackTracesForObject: (id)anObject
Returns an array of stack traces previous recorded with -recordForObject: for the given object.
When no stack traces have been recorded for the given object, returns an empty array.