วิธีที่เชื่อถือได้ในการทำให้แอป iOS ขัดข้องคืออะไร


136

ฉันต้องการทดสอบการรายงานข้อขัดข้องของแอพในฟิลด์โดยตั้งใจว่าจะเกิดข้อผิดพลาดเมื่อผู้ใช้ทำการกระทำเฉพาะที่ผู้ใช้จริงไม่น่าจะทำโดยไม่ตั้งใจ

แต่อะไรคือวิธีที่เชื่อถือได้ดีในการทำให้แอพขัดข้องซึ่งไม่ได้สร้างคำเตือนในเวลารวบรวม

แก้ไข:โปรดทราบว่าคำตอบที่ดูเหมือนจะชัดเจนสำหรับคำถามนี้ส่งผลให้เกิดข้อยกเว้นที่ Cocoa ติดและไม่ส่งผลให้แอปหยุดทำงาน


ฉันเข้าใจWebKit discarded an uncaught exceptionแนวคิดเหล่านี้ทั้งหมดแล้ว! ใครจะรู้ว่ามันยากมากที่จะทำให้แอพพลิเคชั่นขัดข้องในทุกวันนี้?
Nestor

ฉันไม่คิดว่าสิ่งเหล่านี้เกี่ยวข้องกับ WebKit ...
BoltClock

23
ใช่เปิด Safari บน iPad 1 และเรียกดูเพจที่มีรูปภาพจำนวนมาก เหมาะกับฉันเสมอ : /
Alan B

4
(void)0/0;,(void)*(char*)0;
เควิน

1
โปรดใช้ความระมัดระวังกับบางส่วนของคำตอบที่นี่กล่าวอ้างไม่ได้กำหนดพฤติกรรม นั่นเป็นคำแนะนำที่น่ารังเกียจจริงๆ!
usr

คำตอบ:


140

ใน Objective-C ใช้ C โดยตรงเพื่อทำให้เกิดการเข้าถึงที่ไม่ดี

strcpy(0, "bla");

หมายเหตุ: ในขณะที่ระบบนี้ใช้งานได้กับระบบใดก็ได้ที่ฉันรู้ - ใน C runtime runtime รุ่นอนาคตหรือคอมไพเลอร์สิ่งนี้อาจไม่ทำให้เกิดความผิดพลาดอีกต่อไป ดูตัวชี้โมฆะเป็นโมฆะพฤติกรรมไม่ได้กำหนดใน Objective-C? )

(อย่างรวดเร็วคุณจะต้องเชื่อมต่อกับ objC เพื่อทำสิ่งนี้)


นี่คือ IMHO วิธีที่น่าเชื่อถือที่สุด
Michał Kreft

อ่าใช่นั่นก็WebKit discarded an uncaught exceptionแก้ปัญหาด้วยเหมือนกัน
Nestor

ยังมีการพิมพ์ผิด: D no @ "bla" แต่ "bla"
Daij-Djan

4
เห็นได้ชัดว่า ( stackoverflow.com/questions/13651642/ … ) นี่เป็นพฤติกรรมที่ไม่ได้กำหนดและจริงๆแล้วเป็นคำตอบที่แย่มาก! คอมไพเลอร์สามารถเพิ่มประสิทธิภาพทั้งสองข้อความให้ถูกต้องตามกฎหมายและไม่ต้องทำอะไรเลย ฉันแนะนำให้คุณลบคำตอบนี้ อาจนำผู้คนไปทำเช่นนี้จริง
usr

3
บน ios และ osx และ windows และ redhat มันล้มเหลวเสมอดังนั้นในบริบทที่กำหนดฉันจะบอกว่ามันถูกต้อง ฉันจะเพิ่มข้อจำกัดความรับผิดชอบ
Daij-Djan

97

รายการโปรดของฉันในปัจจุบัน:

assert(! "crashing on purpose to test <insert your reason here>");

คลาสสิก:

kill( getpid(), SIGABRT );

และบาง pr0n:

*(long*)0 = 0xB16B00B5;

พวกเขาทั้งหมดสร้างความขัดข้องโดยเครื่องมือรายงานความผิดพลาดของฉัน


14
การยืนยันไม่ผิดพลาดในรุ่นที่วางจำหน่ายนั่นเป็นเหตุผลว่าทำไมจึงเป็นเรื่องยืนยัน
DarthMike

6
มันขึ้นอยู่กับการตั้งค่าการสร้างของคุณ นอกจากนี้ฉันคิดว่าคำถามเกี่ยวกับการทดสอบดูเหมือนว่าจะเก็บการยืนยันในการสร้างการทดสอบ
djromero

3
ผู้คนจำนวนมาก (รวมถึงฉัน) ออกจากการยืนยันในรุ่นบิลด์ ไม่มีเหตุผลที่จะปิดใช้งาน
Sulthan

5
@Sulthan: assert()เป็นคุณสมบัติการแก้ปัญหาทำให้รู้สึกเล็กน้อยที่จะปล่อย cruft ดังกล่าวในการสร้างงาน มีการทดสอบหน่วยสำหรับสิ่งนั้น
MestreLion

18
IMHO assertไม่ใช่คุณสมบัติการแก้ปัญหา การยืนยันที่ล้มเหลวเป็นข้อผิดพลาดที่คุณคิดว่าเป็นไปไม่ได้ มันเป็นการดีกว่าที่จะยกเลิกแม้กระทั่งการสร้างรีลีสมากกว่าการรันโปรแกรมด้วยผลที่ไม่อาจคาดการณ์ได้
djromero

27

เนื่องจากเราทุกคนใช้ Clang สำหรับ iOS สิ่งนี้จึงมีความน่าเชื่อถือ:

__builtin_trap();

สิ่งนี้มีประโยชน์ที่ได้รับการออกแบบมาเพื่อจุดประสงค์นี้อย่างแท้จริงดังนั้นจึงไม่ควรสร้างคำเตือนหรือข้อผิดพลาดของคอมไพเลอร์



22

วิธีการเกี่ยวกับกองเก่าที่ดีล้น :)

- (void)stackOverflow
{
    [self stackOverflow];
}

16

ที่นิยมมากที่สุด - ตัวเลือกที่ไม่รู้จักเกิดความผิดพลาด:

NSObject *object = [[NSObject alloc] init];
[object performSelector:@selector(asfd)];

ตรวจสอบให้แน่ใจว่าคุณไม่ได้ใช้วิธี -asdf ในชั้นเรียนนั้นฮ่าฮ่า

หรือจัดทำดัชนีเกินข้อยกเว้น:

NSArray * array = [NSArray array];
[array objectAtIndex:5];

และแน่นอนว่า kill( getpid(), SIGABRT );


12

ฉันคิดว่าใน Swift คุณสามารถโยนข้อผิดพลาดร้ายแรงได้อย่างง่ายดาย:

func foo() {
    fatalError("crash!")
}

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

เพื่อหลีกเลี่ยงคำสั่ง if ในกรณีพิเศษคุณสามารถใช้preconditionเช่นกัน มันคล้ายกับ assertทำให้ความตั้งใจ (ถ้าต้องการ) ค่อนข้างชัดเจนและไม่ใช่assertเอาออกในรุ่นสุดท้ายเป็น precondition(myBoolean, "This is a helpful error message for debugging.")มันถูกใช้เช่น


9

ส่งข้อความไปยังวัตถุที่ถูกจัดสรรคืน


34
อันนี้ไม่น่าเชื่อถือจริงๆ คุณยังสามารถส่งข้อความไปยังวัตถุที่ถูกจัดสรรคืนตราบใดที่หน่วยความจำไม่ได้ถูกนำมาใช้ซ้ำ นี่คือเหตุผลทั้งหมดที่ผู้คนเคยมีในอดีตยากมากที่จะดีบั๊กข้อผิดพลาดสองครั้ง เป็นเพียงเมื่อหน่วยความจำถูกเรียกคืนโดยวัตถุอื่นที่ส่งข้อความอาจทำให้เกิดข้อยกเว้น
Mike Weller

7
exit(0);

(ต้อง ... พิมพ์ ... 30 ตัวอักษร)


ขอบคุณสำหรับ upvotes แต่ในความเป็นจริงสิ่งนี้จะทำให้แอปยุติและกลับไปที่ Springboard ซึ่งถึงแม้ว่ามันจะมีประโยชน์ในตัวเองไม่ใช่สิ่งที่ OP ต้องการซึ่งจะทำให้เกิดข้อยกเว้นที่ไม่ได้รับการแก้ไข
Steve Rogers

6

คุณสามารถเพิ่มข้อยกเว้น:

[NSException raise:NSInternalInconsistencyException
            format:@"I want to test app crashes!."];

2
ฉันไม่คิดว่าข้อยกเว้นนั้นเป็นวิธีที่ดีการยกเว้นเป็นเรื่องปกติดังนั้นคุณสามารถจับมันได้โดยไม่ตั้งใจ สัญญาณที่จับไม่ได้เป็นเรื่องธรรมดาดังนั้นการเข้าถึงที่ไม่ดีหรือสิ่งที่คล้ายกันน่าเชื่อถือมากขึ้น :)
Michał Kreft

3

เพิ่มตัวรู้จำท่าทางสัมผัสลงในมุมมองที่รับรู้การแตะ 10 นิ้ว (5 นิ้วสำหรับ iPhone ในขณะที่ 10 สามารถแออัดเล็กน้อย) GR มีวิธีการเชื่อมต่อซึ่งจะดำเนินการกับทุกคนที่เคยใช้วิธีที่แน่ใจก่อนหน้านี้เพื่อให้แอปของคุณเสียหาย ผู้ใช้ส่วนใหญ่จะไม่วางนิ้วลงบนแอปของคุณ 10 นิ้วดังนั้นคุณจะปลอดภัยจากผู้ใช้ทั่วไปที่ทำให้เกิดความผิดพลาด

อย่างไรก็ตามคุณควรจะสามารถใช้บางอย่างเช่น Testflight หรือเพียงแค่ปรับใช้กับอุปกรณ์ส่วนบุคคลและทดสอบอย่างรวดเร็วก่อนที่จะส่งไปยัง Apple การมีปัญหาขัดข้องอาจทำให้แอปของคุณถูกปฏิเสธ


แอพ Cocos2d ของฉันขัดข้องเมื่อฉันทำมัลติทัชที่หนักหน่วงที่สุดและฉันก็เป็นเหมือนข้อผิดพลาดที่ยังไม่ได้แก้ไข ฉันไม่มี GR แต่ฉันได้เปิดใช้งานมัลติทัชใน Cocos2d ฉันประสบกับข้อผิดพลาดที่คุณอธิบายหรือไม่ คุณหมายความว่าสิ่งนี้เป็นพฤติกรรมที่ต้องการ / คาดหวัง?
Fredrik Johansson

@ เฟรดริกฉันไม่คิดว่าคุณจะผิดพลาดที่คุณคาดหวังไว้ (ไม่ควรคาดหวังถึงข้อผิดพลาดของ IMO และโดยส่วนตัวฉันไม่คิดว่ามันเป็นความคิดที่ดีที่จะนำแอพของคุณใส่ลงไป คุณสามารถลองใช้สัญลักษณ์แสดงข้อขัดข้องและค้นหาว่าวิธีใดทำให้แอพหยุดทำงาน อาจเป็นสิ่งที่อยู่ในกรอบ Cocos2d ที่ทำให้เกิดความผิดพลาดเมื่อมี 'การสัมผัสหลายจุดที่มากที่สุด' เกิดขึ้น หากเป็นกรณีนั้นทางออกที่ดีที่สุดของคุณคือการยื่นข้อบกพร่องกับพวก Cocos2d
jhelzer

2

ลองทำสิ่งที่ชอบ

NSArray* crashingArray = [NSArray arrayWithCapacity:1];
[crashingArray release];

ควรขัดข้องกับ EXC_BAD_ACCESS (อาจต้องปล่อยเป็นครั้งที่สอง แต่ปกติแล้วมันควรจะผิดพลาดแบบนี้แล้ว)


3
จะไม่คอมไพล์ด้วย ARC ที่เปิดใช้งาน
vikingosegundo

ดีถ้าคุณใช้ ARC คุณสามารถทำได้: NSArray * crashingArray = [NSArray arrayWithCapacity: 1]; [crashingArray objectAtIndex: 0]; นี่ควรจะล้มเหลว
สาลิกา


0

ฉันจะฆ่ากระบวนการตามปกติ:

kill(getpid(), SIGKILL);

ดังนั้นหากคุณติดตั้งตัวจัดการพร้อมสัญญาณคุณสามารถจัดการกับความผิดพลาดได้การเขียนไฟล์ที่เปิดและสิ่งเหล่านี้


นี้รวมอยู่ในคำตอบของ
madmw แล้ว

0

ฉันใช้

[self doesNotRecognizeSelector:_cmd]; 

2
โพสต์นี้ถูกตั้งค่าสถานะโดยอัตโนมัติว่ามีคุณภาพต่ำเนื่องจากเป็นรหัสเท่านั้น คุณจะช่วยขยายความโดยการเพิ่มข้อความเพื่ออธิบายว่าทำไมสิ่งนี้แก้ปัญหาได้หรือไม่
gung - Reinstate Monica



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