Налагодження Xcode 4.2 не символізує дзвінок стека


140

У мене проблема з налагодженням 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)

Дякую.

Відповіді:


256

Нічого, що я намагався, це не виправить (спробував обидва компілятори, обидва налагоджувачі тощо). Після оновлення 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 нижче)

1
Радий це почути :) Мені здається корисним записати журнал аварій у файл та запропонувати користувачеві подати його під час наступного запуску (лише в режимі випуску, щоб не заважати налагодженню). Це дозволяє мені отримувати чудові звіти про помилки ... і користувачі знають, що вирішується їхня проблема :)
Zane Claes

2
Це, здається, не працює - uncaughtExceptionHandlerрутина ніколи не використовується.
Гарячі лизання

1
Чи можете ви уточнити, як це використовувати? Здається, це не працює для мене.
Данут Пралея

1
Досить сумно xCode не відображає це для нас.
Authman Apatira

1
Цінується! Дивовижно, що Apple не реалізує такого роду рудиментарного функціоналу в IDE.
devios1

110

Існує корисний варіант додавання точки виключення (за допомогою + у нижній частині Навігатора точки зупинки). Це порушиться в будь-якому Винятку (або ви можете встановити умови). Я не знаю, чи є цей вибір новим у 4.2 або чи я лише нарешті помітив, що він намагається вирішити проблему відсутніх символів.

Як тільки ви натиснете цю точку розриву, ви можете використовувати Навігатор налагодження для навігації по стеку викликів, вивчення змінних тощо як зазвичай.

Якщо ви хочете, щоб символічний стек викликів підходив для копіювання / вставки або подібного, зворотний шлях gdb спрацює звідти:

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

(тощо)


3
Це для мене чудово працює до цих пір. Зараз налагоджувач зупиняється на лінії зіткнення, немає необхідності в зворотному сліді.
Тім

1
Це чудово працює і для мене. Дякую тобі, що я без розуму пройшов без цієї точки
перерви

+1 для цього спрацювало. Це не дає вам такого приємного повідомлення про помилку, що пояснює причину винятку, але це початок ...
Ніку Сурду,

ти мій HotD @WiseOldDuck.
Maverick1st

Це відновлює очікувану поведінку для мене. ПРИМІТКА. Також не забудьте знову додати цю точку перерви у нових проектах!
MechEthan

46

На відладчику є нова функція. Ви можете встановити точку перерви кожного разу, коли буде викинуто виняток і зупинити виконання саме там, як це було в 4.0.

На "Навігаторі точок розриву" додайте "Точку зупинки винятку" та просто натисніть "Готово" у спливаючому вікні параметрів.

Це все!

PS: У деяких випадках було б краще порушити лише винятки Objective-C.


Напевно це рішення для мене.
bradgonesurfing

Це було проблемою для мене. Ми з колегою ділимось тим самим проектом Xcode, і я запитав його, чи є у нього проблема, а він ні. Різниця була , що його проект розривалося на Objective-C винятків (objc_exception_throw)
horseshoe7

Ви просто допомогли знайти помилку, який не можна відстежувати. Дуже дякую. Я шукав всюди щось подібне.
rjgonzo

1
Це працює як шарм! Це саме те, що я шукав, це краще, ніж додавати обробник винятків, оскільки додавання точки розриву може перенести вас туди, де викинуто виняток, обробник винятків працює, але просто дасть вам уявлення.
im8bit

21

Ось ще одне рішення, не таке елегантне, як попереднє, але якщо ви не додали точки виключення або оброблювачі винятків, це може бути лише один шлях.
Коли програма виходить з ладу, і ви отримуєте ваш необроблений стек викликів першого викиду (у шістнадцяткових номерах), введіть у консоль 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

Ви можете додати точку розриву винятку (використовуючи + у нижній частині Навігатора точки зупинки) та додати bt до неї дії (натисніть кнопку Додати дію, виберіть команду налагодження, введіть "bt" у текстове поле). Це покаже слід стека, як тільки буде викинуто виняток.


6

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

Подайте сюди звіт про помилку.

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

Редагувати:

Я вважаю, що якщо ви повернетеся до LLVM GCC 4.2, ви не побачите цього. Ви можете втратити функції, які вам потрібні.


так, я спробував переключити компілятори, проте проблема залишається. але все-таки спасибі :)
cekisakurek

Він запропонував перемикати налагоджувачі, а не компілятори.
bames53

1
FYI: У цьому випадку це не має нічого спільного з версією компілятора або налагоджувача, яку ви використовуєте. Це зміна консольного виходу з iOS.
clarkcox3

Цікаво, наскільки варіюється досвід цього - я думаю, що є кілька проблем. Мені не вдалося змусити налагоджувача зупинитися на точці розриву виключення. Перехід з GDB на LLDB вирішив проблему.
Метт

6

Використовуйте цей код у своїй головній функції:

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;
}

Це, здається, не працює з розповідями. 2012-06-04 20: 34: 52.211 Проблеми [1944: 207] Делегат програми повинен реалізувати властивість вікна, якщо він хоче використовувати файл основного сценарію. 2012-06-04 20: 34: 52.213 Проблеми [1944: 207] Очікується, що додатки матимуть контролер перегляду коренів у кінці запуску програми
macasas

6

На тип запиту консолі налагодження Xcode:

image lookup -a 0x1234

І це покаже вам щось на кшталт:

  Address: MyApp[0x00018eb0] (MyApp.__TEXT.__text + 91088)
  Summary: MyApp`-[MyViewController viewDidAppear:] + 192 at MyViewController.m:202

Дякую, я справді шукав цього. Дивно, що немає ярлика для відображення всього "стека виклику першого викиду" як стека викликів, бо, мабуть, сценарій Python lldb можна легко записати.
Ілля

1

Увімкнення "Компіляції для великого пальця" (конфігурація налагодження) працювало для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.