我正在尝试测试我的崩溃分析。我没有意识到让应用程序崩溃是多么困难。中编程似乎很简单。有没有人建议我如何强迫我的应用程序崩溃?我并不是说有一点“内存错误”崩溃,我的意思是手机不知道该如何处理自己。在Xcode的组织者中,我至少需要它作为崩溃进入设备日志。有什么建议吗?
答案 0 :(得分:73)
@throw NSInternalInconsistencyException;
答案 1 :(得分:16)
杀死应用程序的方法很多!这是两个一个衬垫:
[self performSelector:@selector(die_die)];
也
@[][666];
答案 2 :(得分:12)
只需写下assert(NO)
即可。这会检查作为参数给出的条件,如果错误,则会崩溃应用程序。
修改强>
exit(0)
也会做到这一点
答案 3 :(得分:9)
int* p = 0;
*p = 0;
提供EXC_BAD_ACCESS (code=2, address=0x0)
修改强>
在格雷格帕克斯评论允许编译器优化上述陈述之后,它让我更加彻底地思考上述陈述,以及为什么格雷格帕克是对的:
实际上,解除引用NULL指针是C和C ++中的“未定义行为”(另请参阅C99§6.5.3.2/ 4)。
这意味着,上述语句的效果取决于编译器。这种“未定义的行为”也意味着允许编译器应用一些优化,这可能会导致上述语句被“优化掉” - 正如Greg Parker断言的那样。
嗯,现在这让我很好奇clang实际上会做什么:
这是一个小测试程序:
int main(int argc, const char * argv[])
{
int* p = 0;
*p = 0;
return 0;
}
优化设置为“-Ofast”,我们得到这个反汇编:
0x100000f90: pushq %rbp
0x100000f91: movq %rsp, %rbp
0x100000f94: ud2
其中ud2
是一个操作码,意思是“未定义的操作码”并导致CPU异常:
`EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)`
(也许@GregParker可以评论为什么clang选择这种方法?)
虽然这很有趣,但它仅指“取消引用NULL指针”。如果我们改为:
int* p = (int*)1;
*p = 0;
程序按预期崩溃 - 但需要硬件拒绝写入此(无效)地址的“先决条件”。
答案 4 :(得分:6)
我认为好的旧数组索引超出范围是“成功崩溃”的保证,所以这里是我最喜欢的列表:
Swift 4 :
[][0]
fatalError()
<强>目标C 强>:
@[][0];
int *x = nil; *x = 0;
虽然@throw NSInternalInconsistencyException;
修复了您的问题,但是异常(不是崩溃),因此可能是caught。
答案 5 :(得分:4)
我经常发现让应用程序启动,稍微做一点,然后在10秒后崩溃很有用。在这种情况下(对于 Objective-C ),我使用:
[self performSelector:NSSelectorFromString(@"crashme:") withObject:nil afterDelay:10];
这样做的第二个好处是编译器不会抛出任何关于未找到选择器的警告(如果使用Objective-C)。 :)
<强>夫特强>:
self.perform("crashme:", with: nil, afterDelay: 10)
答案 6 :(得分:3)
更有效的方法是自己实际抛出异常:
@throw [NSException exceptionWithName:NSGenericException reason:@"" userInfo:nil];
检查NSException.h
是否有更多例外情况。
答案 7 :(得分:2)
对于swift,这些对我有用:
assert(false, "sdf")
而且:
var hey:[Int] = []
hey[0] = 1
答案 8 :(得分:0)
使用 assert()
Swift 允许您使用 assert()
函数强制应用崩溃。这需要两个参数:要检查的条件,以及断言失败时要打印的消息。有用的是,当您的应用在发布模式下编译时(即针对 App Store),对 assert()
的任何调用都会被忽略,这意味着这些检查对您的代码的最终性能没有影响。
以下是使用 assert()
的两个示例:
assert(1 == 2, "Maths failure!")
使用 fatalError()
Swift 有一个名为 fatalError()
的内置函数,它会强制您的应用程序崩溃。这听起来可能很有用,但请耐心等待 - 对于任何认真编写优秀 Swift 的人来说,这是必不可少的功能。
fatalError(
) 函数有一个名为 Never 的特殊返回类型,Swift 将其理解为意味着在调用此函数后将永远不会继续执行。因此,您可以在返回值但没有任何可返回值的方法中使用 fatalError()
。
幸运的是,fatalError()
可以解决这个问题:如果您的类型转换失败,您可以调用 fatalError()
,并显示一条解释发生了什么的消息,如果类型转换失败,您的应用程序将终止
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? MyCustomCell else {
fatalError("Failed to load a MyCustomCell from the table.")
}
return cell
}
答案 9 :(得分:-1)
*(long*)0 = 0xDEADBEEF;
提供EXC_BAD_ACCESS