Отладка Xcode 4.2 не символизирует вызов стека - PullRequest
140 голосов
/ 21 октября 2011

У меня проблема с отладкой Xcode 4.2 в симуляторе / устройстве iOS 5.Следующий код вылетает, как и ожидалось:

NSArray *arr=[NSArray array];
[arr objectAtIndex:100];

В iOS 4 я получаю полезную трассировку стека шестнадцатеричных чисел.Но в iOS 5 он просто дает мне:

*** First throw call stack:
(0x16b4052 0x1845d0a 0x16a0674 0x294c 0x6f89d6 0x6f98a6 0x708743 0x7091f8 0x7fcaa9 0x2257fa9 0x16881c5 0x15ed022 0x15eb90a 0x15eadb4 0x15eaccb 0x6f02a7 0x6faa93 0x2889 0x2805)

Спасибо.

Ответы [ 9 ]

255 голосов
/ 26 октября 2011

Ничто из того, что я пробовал, не исправило бы это (пробовал оба компилятора, оба отладчика и т. Д.) После обновления XCode для обновления iOS 5 трассировка стека, похоже, не работала.

Однако я нашел эффективный обходной путь - создание собственного обработчика исключений (что также полезно по другим причинам). Сначала создайте функцию, которая будет обрабатывать ошибку и выводить ее на консоль (а также все, что вы хотите с ней сделать):

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

Затем добавьте обработчик исключений в делегат приложения:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
    // Normal launch stuff
}

Вот и все!

Если это не работает, то есть только две возможные причины :

  1. Что-то перезаписывает ваш NSSetUncaughtExceptionHandler вызов (для всего вашего приложения может быть только один обработчик). Например, некоторые сторонние библиотеки устанавливают свои собственные uncaughtExceptionHandler. Поэтому попробуйте установить его в КОНЕЦ вашей функции didFinishLaunchingWithOptions (или выборочно отключить сторонние библиотеки). Или, что еще лучше, установите символическую точку останова на NSSetUncaughtExceptionHandler, чтобы быстро увидеть, кто ее вызывает. Что вы можете сделать, это изменить текущий, а не добавлять другой.
  2. Вы на самом деле не сталкиваетесь с исключением (например, EXC_BAD_ACCESS - это , а не - исключение; благодарность за комментарии @Erik B ниже)
109 голосов
/ 27 октября 2011

Существует полезная опция добавления точки останова исключения (с помощью + в нижней части навигатора точки останова). Это будет нарушать любое исключение (или вы можете установить условия). Я не знаю, является ли этот выбор новым в 4.2 или я только наконец заметил, что пытается обойти проблему пропущенных символов.

Как только вы достигнете этой точки останова, вы можете использовать отладочный навигатор для навигации по стеку вызовов, для проверки переменных и т. Д. Как обычно.

Если вы хотите использовать символьный стек вызовов, подходящий для копирования / вставки и т. П., Обратная трассировка GDB будет работать нормально:

(gdb) bt
#0  0x01f84cf0 in objc_exception_throw ()
#1  0x019efced in -[NSObject doesNotRecognizeSelector:] ()

(и т.д.)

46 голосов
/ 03 ноября 2011

В отладчике появилась новая функция. Вы можете установить точку останова всякий раз, когда выдается исключение, и сразу же останавливать выполнение, как это происходило в 4.0.

В «Навигаторе точек останова» добавьте «Точку останова исключений» и просто нажмите «Готово» во всплывающем окне опций.

Вот и все!

PS: в некоторых случаях лучше разбивать только для исключений Objective-C.

21 голосов
/ 15 января 2012

Вот еще одно решение, не такое элегантное, как в предыдущем случае, но если вы не добавили точки останова или обработчики исключений, это может быть только один путь.
Когда приложение падает, и вы получаете исходное значение стек вызовов первого выброса (в шестнадцатеричных числах), введите в консоль Xcode info line *hex (не забудьте звездочку и шестнадцатеричный спецификатор 0x), например:

(gdb) info line *0x2658
Line 15 of "path/to/file/main.m" starts at address 0x25f2 <main+50>
and ends at 0x267e <main+190>.

Если выиспользуя lldb , вы можете набрать image lookup -a hex (без звездочки в этой ситуации), и вы получите аналогичный вывод.

С помощью этого метода вы можете перемещаться с вершины стека броска (тамбудет около 5-7 распространителей системных исключений) для вашей функции, которая вызвала сбой, и определит точный файл и строку кода.

Кроме того, для аналогичного эффекта вы можете использовать утилиту atos в терминале, просто наберите:

atos -o path/to/AplicationBundle.app/Executable 0xAdress1 0xAdress2 0xAdress3 ...

и вы получите символическую трассировку стека (по крайней мере, для функций у вас есть символы отладки).Этот метод более предпочтителен, поскольку у вас нет для каждого вызова адреса info line, просто скопируйте адреса из вывода консоли и вставьте их в терминал.

9 голосов
/ 26 октября 2012

Вы можете добавить исключительную точку останова (используя + в нижней части навигатора точек останова) и добавить к ней действие bt (нажмите кнопку Добавить действие, выберитеКоманда отладчика, введите «bt» в текстовое поле).Это отобразит трассировку стека, как только будет сгенерировано исключение.

6 голосов
/ 31 октября 2013

В командной строке отладки Xcode введите:

image lookup -a 0x1234

И он покажет вам что-то вроде:

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202
6 голосов
/ 13 февраля 2012

Используйте этот код в вашей основной функции:

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;
}
6 голосов
/ 21 октября 2011

Это распространенная проблема, не получая трассировки стека в 4.2.Вы можете попробовать переключиться между LLDB и GDB, чтобы увидеть, если вы получите лучшие результаты.

Подайте отчет об ошибке здесь.

http://developer.apple.com/bugreporter/

РЕДАКТИРОВАТЬ:

Я полагаю, что если вы вернетесь к LLVM GCC 4.2, этого не произойдет.Однако вы можете потерять нужные вам функции.

1 голос
/ 26 января 2012

Повторное включение 'Compile for Thumb' (отладочная конфигурация) мне помогло.

...