views:

58

answers:

3

Objective-C's runtime seems to be rather robust, so I was wondering if there's a way to log the name of the function that called the current function (for debugging purposes).

My situation is that a bunch of things assign to a property, and rather than set a breakpoint and examine the call stack each time, I'd like to just NSLog the name of the function that is setting the property, along with the new value.

So is it possible to get access to the call stack at runtime?

+1  A: 

There is no facility for getting the sender. Or, at least, nothing centric to Objective-C.

There are a couple of alternatives, though.

First, you could use GDB commands. Go to the GDB console and do something like:

comm 1
bt
po argName
cont

Alternatively, you could use dtrace. This is hard. Or you could use Instruments which makes dtrace somewhat easier.

Or you could use the backtrace() function. See the backtrace man page (x-man-page://backtrace).

bbum
A: 

There is a C macro called __PRETTY_FUNCTION__ that will return a C-String with the name of the current function. If you would like to convert that to an NSString for easily printing to NSLog, you can create a macro with

#define NSSTRING_PRETTY_FUNCTION [NSString stringWithCString:__PRETTY_FUNCTION__ encoding:NSASCIIStringEncoding]

I use it all the time in my projects.

Joe Ibanez
You didn't read the question properly. It's not the name of the current function that is needed, but the caller.
JeremyP
+3  A: 

Try this:

#include <execinfo.h>

void *addr[2];
int nframes = backtrace(addr, sizeof(addr)/sizeof(*addr));
if (nframes > 1) {
    char **syms = backtrace_symbols(addr, nframes);
    NSLog(@"%s: caller: %s", __func__, syms[1]);
    free(syms);
} else {
    NSLog(@"%s: *** Failed to generate backtrace.", __func__);
}
Jeremy W. Sherman
This works great if you replace `sizeof(addr)` with `sizeof(addr) / sizeof(void*)` (or just 2). Thanks!
Brian
Fixed. Oh, and Foundation actually exposes this really simply via `-[NSThread callStackSymbols]`, which returns an array. You could use it as `NSArray *syms = [[NSThread currentThread] callStackSymbols]; if ([syms count] > 1) NSLog(@"caller: %@", [syms objectAtIndex:1U];`
Jeremy W. Sherman