2010-10-28 11 views
30

El tiempo de ejecución de Objective-C parece bastante robusto, por lo que me preguntaba si hay una forma de registrar el nombre de la función que llamó a la función actual (para depuración).Imprime el nombre de la función de llamada al registro de depuración

Mi situación es que un montón de cosas se asignan a una propiedad, y en lugar de establecer un punto de interrupción y examinar la pila de llamadas cada vez, me gustaría simplemente NSLog el nombre de la función que establece la propiedad, junto con el nuevo valor

Entonces, ¿es posible acceder a la pila de llamadas en tiempo de ejecución?

Respuesta

42

Prueba esto:

#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__); 
} 
+0

Esto funciona muy bien si reemplaza 'sizeof (addr)' con 'sizeof (addr)/sizeof (void *)' (o solo 2). ¡Gracias! – Brian

+14

Reparado. Ah, y Foundation realmente expone esto realmente simplemente a través de '- [NSThread callStackSymbols]', que devuelve una matriz. Puede usarlo como 'NSArray * syms = [[NSThread currentThread] callStackSymbols]; if ([syms count]> 1) NSLog (@ "caller:% @", [syms objectAtIndex: 1U]; ' –

+5

último comentario:' callStackSymbols' es un método de clase. Debe usarlo como '[NSThread callStackSymbols]' – user102008

2

No hay ninguna posibilidad para obtener el remitente. O, al menos, nada centrado en Objective-C.

Sin embargo, hay un par de alternativas.

En primer lugar, podría utilizar los comandos de GDB. Vaya a la consola de GDB y haga algo como:

comm 1 
bt 
po argName 
cont 

O bien, puede usar dtrace. Esto es duro. O podrías usar Instrumentos que hace que dtrace sea algo más fácil.

O podría utilizar la función backtrace(). Consulte la página del manual de traza inversa (x-man-page: // traza inversa).

0

Hay una macro C llamada __PRETTY_FUNCTION__ que devolverá una C-String con el nombre de la función actual. Si desea convertir eso a un NSString para imprimir fácilmente a NSLog, puede crear una macro con

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

lo uso todo el tiempo en mis proyectos.

+4

No ha leído la pregunta correctamente. No es el nombre de la función actual que se necesita, sino la persona que llama. – JeremyP

30

Gran Pregunta. Combinando la respuesta de Jeremy anterior y lo que siempre usamos para nuestra depuración, obtendrá una buena cadena como esta:

NSArray *syms = [NSThread callStackSymbols]; 
if ([syms count] > 1) { 
    NSLog(@"<%@ %p> %@ - caller: %@ ", [self class], self, NSStringFromSelector(_cmd),[syms objectAtIndex:1]); 
} else { 
    NSLog(@"<%@ %p> %@", [self class], self, NSStringFromSelector(_cmd)); 
} 
+0

¿Necesitas llamar a este fragmento de código? – Shamsiddin

+0

Sí, necesitas llamarlo a la función correspondiente donde deseas iniciar sesión. llama. – LordT

+0

Hice como dijiste, pero no imprimió todas las hist ory de los métodos trabajados comienzan desde la ejecución del proyecto. – Shamsiddin

Cuestiones relacionadas