ios - programacion - swift para windows
La depuraciĆ³n de Xcode 4.2 no simboliza la llamada a la pila (9)
Tengo un problema con la depuración de Xcode 4.2 en un simulador / dispositivo iOS 5. El siguiente código falla, como se esperaba:
NSArray *arr=[NSArray array];
[arr objectAtIndex:100];
En iOS 4, obtengo un rastro de pila útil de números hexadecimales. Pero en iOS 5, simplemente me da:
*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)
Gracias.
Aquí hay una solución más, no tan elegante como la anterior, pero si no agregaste puntos de interrupción o manejadores de excepción, puede ser solo un camino a seguir.
Cuando la aplicación falla, y obtienes la pila de llamadas en primer intento sin formato (en números hexadecimales), escribe en la info line *hex
consola Xcode info line *hex
(no olvides la estrella y el especificador hexadecimal 0x
), por ejemplo:
(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.
Si está utilizando lldb , puede escribir image lookup -a hex
(sin estrella en esta situación), y obtendrá resultados similares.
Con este método, puede atravesar desde la parte superior de la pila de tiro (habrá alrededor de 5-7 propagadores de excepciones del sistema) a su función, lo que provocó un bloqueo y determinar el archivo y la línea de código exactos.
Además, para efectos similares puede usar la utilidad atos en la terminal, solo escriba:
atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...
y obtiene la traza de la pila simbolizada (al menos para las funciones que tiene símbolos de depuración). Este método es más preferible, ya que no tiene para cada info line
llamada de dirección, solo copie las direcciones de la salida de la consola y péguelas en la terminal.
En la solicitud de depuración de Xcode, escriba:
image lookup -a 0x1234
Y te mostrará algo así como:
Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202
Este es un problema común, no obtener rastros de pila en 4.2. Puedes intentar intercambiar entre LLDB y GDB para ver si obtienes mejores resultados.
Presente un informe de error aquí.
http://developer.apple.com/bugreporter/
EDITAR:
Creo que si cambias a LLVM GCC 4.2 no verás que esto suceda. Sin embargo, puede perder las características que necesita.
Existe una opción útil para agregar un Punto de interrupción de excepción (usando el + en la parte inferior del Navegador de punto de interrupción). Esto romperá cualquier Excepción (o puede establecer condiciones). No sé si esta elección es nueva en 4.2 o si finalmente lo noté tratando de resolver el problema de los símbolos faltantes.
Una vez que llegue a este punto de interrupción, puede usar el Navegador de depuración para navegar por la pila de llamadas, examinar variables, etc., como de costumbre.
Si desea una pila de llamadas simbolizada adecuada para copiar / pegar o similar, gdb backtrace funcionará bien desde allí:
(gdb) bt
#0 0x01f84cf0 in objc_exception_throw ()
#1 0x019efced in -[NSObject doesNotRecognizeSelector:] ()
(etc.)
Hay una nueva característica en el depurador. Puede establecer un punto de interrupción cada vez que se lanza una excepción y detener la ejecución allí mismo, tal como solía ocurrir en 4.0.
En el "Navegador de punto de interrupción", agregue un "Punto de interrupción de excepción" y simplemente presione "Listo" en la ventana emergente de opciones.
¡Eso es todo!
PD: en algunos casos sería mejor romper solo para excepciones de Objective-C.
Nada de lo que intenté solucionaría esto (intenté con los compiladores, los depuradores, etc.) Después de actualizar XCode para la actualización de iOS 5, no parecía que hubiera ningún rastro de pila.
Sin embargo, he encontrado una solución efectiva: crear mi propio manejador de excepciones (que también es útil por otros motivos). Primero, cree una función que manejará el error y lo enviará a la consola (así como a cualquier otra cosa que quiera hacer con él):
void uncaughtExceptionHandler(NSException *exception) {
NSLog(@"CRASH: %@", exception);
NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
// Internal error reporting
}
A continuación, agregue el manejador de excepciones al delegado de su aplicación:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// Normal launch stuff
}
¡Eso es!
Si esto no funciona, solo hay dos posibles razones :
- Algo sobrescribe su llamada
NSSetUncaughtExceptionHandler
(solo puede haber un controlador para toda su aplicación). Por ejemplo, algunas bibliotecas de terceros establecen su propio uncaughtExceptionHandler. Por lo tanto, intente configurarlo al FINAL de su funcióndidFinishLaunchingWithOptions
(o deshabilitar selectivamente las bibliotecas de terceros). O mejor aún, establezca un punto deNSSetUncaughtExceptionHandler
simbólico enNSSetUncaughtExceptionHandler
para ver rápidamente quién lo está llamando. Lo que puede hacer es modificar su actual en lugar de agregar otra. - En realidad, no se encuentra con una excepción (por ejemplo,
EXC_BAD_ACCESS
no es una excepción; acceda a los comentarios de @Erik B, a continuación)
Puede agregar un Punto de interrupción de excepción (usando + en la parte inferior del Navegador de punto de interrupción) y agregarle la acción bt
(haga clic en el botón Agregar acción, seleccione Comando del depurador, ingrese "bt" en el campo de texto). Esto mostrará el seguimiento de pila tan pronto como se genere una excepción.
Usa este código en tu función principal:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal;
@try {
retVal = UIApplicationMain(argc, argv, nil, nil);
}
@catch (NSException *exception) {
NSLog(@"CRASH: %@", exception);
NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
}
@finally {
[pool release];
}
return retVal;
}
Volví a activar ''Compilar para pulgar'' (configuración de depuración).