运行时解引用nullptr是否必然导致段错误?
摘要
- 若在运行时对满足
p == nullptr的指针p进行解引用,并读取/写入其指向对象,会发生什么? - 这是否必然会导致段错误,因为内存地址0无法被读写?
我特意强调“运行时”的原因是,我了解编译器在看到*p(p为裸指针)时会假设p != nullptr,因此某些*p操作可能会因未定义行为(UB)而被优化掉,实际运行时并不会真正解引用nullptr,程序会沿着未定义行为的路径继续执行。
例如,给定以下翻译单元(TU):
int* bar(); int foo(int* i) { return *i; } int work() { int* b = bar(); int f = foo(b); return b != nullptr ? 0 : (f + *bar()); }
编译器仅通过观察foo函数体对bar()的返回值进行解引用,就可以假设bar() != nullptr,因为只有bar() != nullptr时该操作才合法。实际上,work函数被编译为:
work(): sub rsp, 8 call bar() xor eax, eax add rsp, 8 ret
其中bar()的返回值从未被实际解引用,尽管源代码中存在*bar()。
但如果foo单独位于一个翻译单元中(此时不存在未定义行为),它会被编译为:
foo(int*): mov eax, DWORD PTR [rdi] ret
若该翻译单元与另一个调用foo(nullptr)的单元链接,那么mov指令肯定会尝试读取rdi中的地址,也就是nullptr被编译后的地址(推测为0)。
这是否意味着段错误不可避免?(我并非想避免段错误,恰恰相反,我只是想知道是否会出现更严重的情况:无段错误且程序继续执行,走向未知!)
(¹) 我了解解引用空指针是否属于未定义行为的问题仍未解决,但这并非我之前问题的重复。
内容的提问来源于Stack Exchange,提问作者Enlico
相关产品推荐
相关产品推荐

