为什么解除空指针引用不会导致程序崩溃?

4

我写下了以下代码来引发崩溃(我正在测试CrashReporter的一些问题):

int *nullp = NULL;
int val = *nullp;    
NSLog(@"Hello world %d", val);

在一个全新的项目中(我将它放在应用委托的applicationDidFinishLaunching:中),它会如预期一样崩溃。但是当我将它添加到我的现有项目之一时,它并不崩溃!实际上,它最终会将“Hello world 0”打印到系统日志中。
这对我来说毫无意义。为什么空指针解引用不会导致崩溃?

2
如果需要,可以使用其他导致崩溃的选项:不使用强制转换使C崩溃 - jscs
3个回答

8

解引用NULL的行为是未定义的,它不一定会导致崩溃。

话虽如此,如果您在两个项目中使用不同的编译器选项,则很有可能在这些情况下获得不同的行为。请参阅LLVM博客文章了解未定义行为。


谢谢,我不知道。那个链接帮助我让它崩溃了:“如果你正在使用基于LLVM的编译器,你可以解引用一个'volatile'空指针来获得崩溃,因为volatile加载和存储通常不会被优化器触及。” - pepsi
1
那篇帖子在我一个月或两个月前第一次阅读时让我大开眼界。 - MByD
对于那些不太熟悉 C 语言的人来说,值得指出的是,这意味着您需要将 nullp 声明为 volatile int *nullp = NULL; - Rob Keniger
3
那篇文章唯一的坏建议是使用volatile变量。如果你真的想要在Clang下强制崩溃,可以使用__builtin_trap() - Jens Ayton
2
或者更具可移植性的方式是 raise(SIGTRAP)abort()。后者是 Clang 在没有陷阱指令的架构上所做的操作 - Peter Hosey

2

对空指针进行解引用是未定义行为 - 也就是说,没有规定它一定会使你的应用程序崩溃。

不同编译器将给出不同的结果 - 不同的编译器选项(例如发布与调试配置)也会影响结果。

如果您想强制崩溃,可以始终开始向空指针写入内容...


在向空指针写入数据时,很可能会导致崩溃,但并不是绝对的。未定义也意味着不可预测,除非您对编译器和处理器架构非常熟悉,并且两者都没有改变,否则无法百分之百地保证。 - Mark Ransom

-1

int *nullp = NULL; 或 int *nullp = 0 是相同的,它意味着指针 nullp 没有指向任何内存位置。由于 NULL == 0,它会打印零而不会崩溃。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接