[英]What's the quickest way to force an iOS app to crash?
我正在尝试测试我的崩溃分析。 我没有意识到随意让应用程序崩溃是多么困难。 中间编程似乎如此简单。 有人对我如何强制我的应用程序崩溃有任何建议吗? 我的意思不是一点“内存错误”崩溃,我的意思是手机不知道如何处理自己。 我需要它至少在 Xcode 的管理器中作为崩溃进入设备日志。 有什么建议?
@throw NSInternalInconsistencyException;
杀死应用程序的方法有很多! 这是两个合一的衬垫:
[self performSelector:@selector(die_die)];
还
@[][666];
只需写assert(NO)
。 这会检查作为参数给出的条件,如果为 false,则应用程序崩溃。
编辑:
exit(0)
也能解决问题
int* p = 0;
*p = 0;
给出一个EXC_BAD_ACCESS (code=2, address=0x0)
编辑:
在 Greg Parkers 评论说允许编译器优化掉上述语句之后,这让我更彻底地思考了上述语句,以及为什么 Greg Parker 是对的:
事实上,在 C 和 C++ 中取消引用 NULL 指针是“未定义行为”(另请参见 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 :
[][0]
fatalError()
目标-C :
@[][0];
int *x = nil; *x = 0;
虽然@throw NSInternalInconsistencyException;
解决您的问题,是一个异常(不是崩溃),因此可能会被捕获。
我经常发现让应用程序启动,做一些事情,然后在 10 秒后崩溃很有用。 在这种情况下(对于Objective-C ),我使用:
[self performSelector:NSSelectorFromString(@"crashme:") withObject:nil afterDelay:10];
这样做的第二个好处是编译器不会抛出任何关于未找到选择器的警告(如果使用 Objective-C)。 :)
斯威夫特:
self.perform("crashme:", with: nil, afterDelay: 10)
一种更可控的方法是自己实际抛出异常:
@throw [NSException exceptionWithName:NSGenericException reason:@"" userInfo:nil];
检查NSException.h
以获取更多异常。
对于 swift 这些对我有用:
assert(false, "sdf")
和这个:
var hey:[Int] = []
hey[0] = 1
用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
}
*(long*)0 = 0xDEADBEEF;
给出 EXC_BAD_ACCESS
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.