使iOS应用程序崩溃的可靠方法是什么?


136

我想通过在用户执行实际用户不太可能意外执行的特定操作时故意使应用程序崩溃来测试我的应用程序的崩溃报告。

但是,使应用程序崩溃而不在编译时发出警告的一种可靠的可靠方法是什么?

编辑:请注意,此问题的许多看似显而易见的答案会导致可可捕获到异常,因此不会导致应用崩溃。


WebKit discarded an uncaught exception到目前为止,我已经了解了所有这些想法!谁知道这些天使应用程序崩溃是如此困难?
Nestor 2012年

我认为这些都不与WebKit有任何关系...
BoltClock

23
是的,在iPad 1上打开Safari,然后浏览到包含大量图像的页面。永远为我工作。:/
Alan B

4
(void)0/0;(void)*(char*)0;
凯文

1
请谨慎使用此处未定义行为的一些答案。这实际上是非常讨厌的建议!
usr

Answers:


140

在Objective-C中直接使用C导致错误的访问

strcpy(0, "bla");

注意:虽然这在我知道的任何系统上都可以使用-在C运行时的将来版本或编译器中,这可能不再导致崩溃。请参见在Objective-C中空指针取消引用是未定义的行为吗?

(很快,您必须桥接到objC来执行此操作)


这是恕我直言,最可靠的方式
米哈尔Kreft

是的,这也解决了WebKit discarded an uncaught exception问题。
Nestor 2012年

仍然有错别字:D no @“ bla” but“ bla”
Daij-Djan 2012年

4
显然(stackoverflow.com/questions/13651642/…),这是未定义的行为,实际上是一个很糟糕的答案!编译器可以合法地优化两个语句,并且什么也不做。我建议您删除此答案。它可能会导致人们实际执行此操作。
usr

3
在ios,osx,windows和redhat上,它总是崩溃了,因此在给定的上下文中,我想说它是有效的。我将添加免责声明
Daij-Djan 2012年

97

我当前的最爱:

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

经典:

kill( getpid(), SIGABRT );

还有一些pr0n:

*(long*)0 = 0xB16B00B5;

所有这些都会生成由崩溃报告工具捕获的崩溃。


14
断言不会在发行版本上崩溃,这就是为什么要断言的原因
DarthMike 2012年

6
这取决于您的构建设置;另外,我认为问题是关于测试的,在测试版本中保留主张似乎是可以的
djromero 2012年

3
很多人(包括我)在发布版本中保留断言。没有理由禁用它们。
苏珊(Sulthan)2012年

5
@Sulthan:assert()是一种调试功能,将这样的问题留在发行版中几乎没有意义。对此有单元测试。
MestreLion,2012年

18
IMHO assert不是调试功能。断言失败是您认为不可能的错误。最好中止甚至是发行版本,而不是继续运行程序以产生无法预料的后果。
djromero 2012年

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 2012年

7
exit(0);

(必须...输入... 30个字符)


感谢您的支持,但实际上这将使该应用终止并返回到Springboard,尽管它本身可能有用,但并不是OP想要的,而是触发了未捕获的异常
Steve Rogers

6

您还可以引发异常:

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

2
我认为异常不是那种好方法,捕获异常很常见,因此您可能会意外捕获它。捕获信号并不常见,因此访问不当或类似的情况会更可靠。:)
米哈尔Kreft

3

将手势识别器添加到可识别10指轻击的视图(iPhone上为5指,因为10会有点拥挤)。GR附带有一个方法,该方法执行前面提到的任何surefire方法中的任何一种都会使您的应用崩溃。大多数用户不会在您的应用程序上放十根手指,因此可以避免普通用户意外导致崩溃。

但是,您应该能够使用诸如Testflight之类的东西,或者只是将其部署到个人设备上并进行野外测试,然后再将其提交给Apple。强制崩溃可能会导致您的应用被Apple拒绝。


当我进行极端的多点触控时,我的Cocos2d应用程序崩溃了,并且我已经将其作为一个未解决的错误。我没有任何GR,但已在Cocos2d中启用了多点触控。我会遇到您描述的崩溃吗?您是说这是预期的/有害的行为?
Fredrik Johansson

@Fredrik我不认为您正在描述的崩溃是预期的(IMO崩溃绝不应该发生,我个人认为为此故意在应用程序中放一个不是个好主意)。您可以尝试象征崩溃,并找出导致应用崩溃的确切方法。可能是Cocos2d框架内的某些东西在发生“极端多点触摸”时导致崩溃。如果真是这样,那么您最好的选择是向Cocos2d团队提交错误。
jhelzer 2012年

2

可以尝试像

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

应该在EXC_BAD_ACCESS上崩溃(可能需要再次释放它,但通常它应该已经这样崩溃了)


3
无法在启用ARC的情况下进行编译。
vikingosegundo 2012年

如果您使用ARC,也可以这样做:NSArray * crashingArray = [NSArray arrayWithCapacity:1]; [crashingArray objectAtIndex:0]; 这应该崩溃
Saliom



0

我用

[self doesNotRecognizeSelector:_cmd]; 

2
由于仅是代码,因此该帖子被自动标记为低质量。您介意添加一些文本来解释为什么它可以解决问题吗?
gung-恢复莫妮卡2014年

0

在使用RubyMotion时,我使用以下代码:

    n=Pointer.new ('c', 1)
    n[1000] ='h'


-1

错误的NSLog陈述会做到这一点

NSLog(@"%@",1);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.