การดีบัก 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 ขด้านล่าง)

1
ดีใจที่ได้ยิน :) ฉันคิดว่ามันมีประโยชน์ในการเขียนบันทึกความผิดพลาดไปยังไฟล์และแจ้งให้ผู้ใช้ส่งมันในการเปิดตัวครั้งถัดไป (ในโหมดการวางจำหน่ายเท่านั้น นี้จะช่วยให้ฉันได้รับรายงานข้อผิดพลาดที่ยิ่งใหญ่ ... และผู้ใช้รู้ว่าปัญหาของพวกเขาจะถูกจ่าหน้า :)
Zane Claes

2
สิ่งนี้ดูเหมือนจะไม่ทำงาน - uncaughtExceptionHandlerรูทีนจะไม่ถูกเรียกใช้
Hot Licks

1
คุณช่วยอธิบายวิธีใช้มันให้ละเอียดมากขึ้นได้ไหม? ดูเหมือนจะไม่ได้ผลสำหรับฉัน
Danut Pralea

1
xCode ที่น่าเศร้าไม่ได้แสดงสิ่งนี้ให้เราเห็น
Authman Apatira

1
ชื่นชมมาก! เป็นเรื่องที่น่าแปลกใจที่ Apple ไม่ได้ใช้ฟังก์ชั่นพื้นฐานดังกล่าวใน IDE
devios1

110

มีตัวเลือกที่มีประโยชน์ในการเพิ่มจุดพักข้อยกเว้น (ใช้ + ที่ด้านล่างของตัวหยุดจุดพัก) สิ่งนี้จะขัดกับข้อยกเว้นใด ๆ (หรือคุณสามารถกำหนดเงื่อนไข) ฉันไม่รู้ว่าตัวเลือกนี้เป็นของใหม่ใน 4.2 หรือในที่สุดฉันก็สังเกตเห็นว่ามันพยายามที่จะแก้ไขปัญหาสัญลักษณ์ที่หายไป

เมื่อคุณกดเบรกพอยต์นี้คุณสามารถใช้ Debug Navigator เพื่อนำทางไปยัง call stack ตรวจสอบตัวแปรและอื่น ๆ ตามปกติ

หากคุณต้องการ call stack symbolically เหมาะสำหรับการคัดลอก / การวางหรือสิ่งที่คล้ายกัน gdb backtrace จะทำงานได้ดีจากที่นั่น:

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

( ฯลฯ )


3
มันทำงานได้อย่างสมบูรณ์แบบสำหรับฉันจนถึงตอนนี้ ตัวดีบักหยุดทำงานบนบรรทัดหยุดทำงานตอนนี้ไม่จำเป็นต้องย้อนกลับ
ทิม

1
มันเหมาะกับฉันเช่นกัน ขอบคุณมากผมจะบ้าโดยไม่ต้องเบรกพอยต์นี้ ...
วิลเลียม Denniss

+1 สำหรับมันใช้งานได้ มันไม่ได้ให้ข้อความแสดงข้อผิดพลาดที่ดีอธิบายเหตุผลของข้อยกเว้น แต่มันเป็นจุดเริ่มต้น ...
Nicu Surdu

คุณคือ HotD ของฉัน @WiseOldDuck
Maverick1st

สิ่งนี้จะคืนค่าพฤติกรรมที่คาดหวังสำหรับฉัน หมายเหตุ: นอกจากนี้อย่าลืมเพิ่มเบรกพอยต์นี้ในโครงการใหม่!
MechEthan

46

มีคุณสมบัติใหม่ในการดีบัก คุณสามารถตั้งจุดพักเมื่อใดก็ตามที่มีข้อยกเว้นเกิดขึ้นและหยุดการประมวลผลที่นั่นเช่นเดียวกับที่เคยเกิดขึ้นกับ 4.0

ใน "เบรกพอยต์นาวิเกเตอร์" เพิ่ม "จุดพักข้อยกเว้น" และเพียงกด "เสร็จสิ้น" บนป๊อปอัพตัวเลือก

นั่นคือทั้งหมด!

PS: ในบางกรณีจะดีกว่าที่จะทำลายเฉพาะสำหรับข้อยกเว้น Objective-C


แน่นอนนี่เป็นทางออกสำหรับฉัน
bradgonesurfing

นี่คือปัญหาสำหรับฉัน เพื่อนร่วมงานและฉันแบ่งปันโครงการ Xcode เดียวกันและฉันถามเขาว่าเขามีปัญหาหรือไม่ ความแตกต่างคือโปรเจ็กต์ของเขากำลังทำลายข้อยกเว้นในวัตถุประสงค์ -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 ...

และคุณจะได้รับการติดตามสแต็กแบบมีสัญลักษณ์ (อย่างน้อยสำหรับฟังก์ชั่นที่คุณมีสัญลักษณ์ดีบัก) วิธีนี้เป็นวิธีที่ดีกว่าเพราะคุณไม่มีสำหรับการเรียก adress แต่ละครั้งinfo lineเพียงแค่คัดลอกที่อยู่จากคอนโซลเอาต์พุตและวางลงในเทอร์มินัล


9

คุณสามารถเพิ่มจุดพักข้อยกเว้น (ใช้ + ที่ด้านล่างของเบรกพอยต์นาวิเกเตอร์) และเพิ่มการกระทำ bt (คลิกที่ปุ่มเพิ่มแอ็คชั่นเลือกคำสั่งดีบักเกอร์ป้อน "bt" ในฟิลด์ข้อความ) สิ่งนี้จะแสดงการติดตามสแต็กทันทีที่มีการโยนข้อยกเว้น


6

นี่เป็นปัญหาทั่วไปที่ไม่ได้รับการติดตามสแต็กใน 4.2 คุณสามารถลองสลับระหว่าง LLDB และ GDB เพื่อดูว่าคุณได้ผลลัพธ์ที่ดีขึ้นหรือไม่

ยื่นรายงานข้อผิดพลาดที่นี่

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

แก้ไข:

ฉันเชื่อว่าถ้าคุณสลับกลับไปที่ LLVM GCC 4.2 คุณจะไม่เห็นสิ่งนี้เกิดขึ้น คุณอาจสูญเสียคุณสมบัติที่คุณต้องการ


ใช่ฉันพยายามเปลี่ยนคอมไพเลอร์ แต่ปัญหายังคงอยู่ แต่ขอบคุณ anyways :)
cekisakurek

เขาแนะนำการสลับดีบัคเกอร์ไม่ใช่คอมไพเลอร์
bames53

1
FYI: ในอินสแตนซ์นี้ไม่มีส่วนเกี่ยวข้องกับเวอร์ชันของคอมไพเลอร์หรือดีบั๊กที่คุณใช้ นี่คือการเปลี่ยนแปลงในเอาต์พุตคอนโซลจาก iOS
clarkcox3

น่าสนใจว่าประสบการณ์มากมายของสิ่งนี้แตกต่างกันไป - ฉันคิดว่ามีปัญหาเล็กน้อย ฉันไม่สามารถให้ตัวดีบักหยุดที่จุดพักข้อยกเว้น การเปลี่ยนจาก GDB เป็น LLDB แก้ปัญหาได้
Matt

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 สามารถเขียนได้อย่างง่ายดาย
Ilya

1

การเปิดใช้งาน 'คอมไพล์สำหรับนิ้วหัวแม่มือ' (การดีบักการกำหนดค่า) ทำงานให้ฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.