空指针的运行时取消引用是否总是会导致分段错误?

问题描述 投票:0回答:1

tl;博士

如果 “运行时” 一个指针

p
使得
p == nullptr
被取消引用并且读取/写入其“指向对象”,会发生什么?

这是否意味着 100% 存在分段错误,因为内存地址 0 不能被读取/写入?


我之所以写“在运行时”,是因为我知道编译器在看到

p != nullptr
(使用
*p
原始指针)时会假设
p
,所以一些
 *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());
}

编译器只需查看其返回值被

bar() =! nullptr
的主体取消引用即可假定
foo
,这只能在
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

因此,如果这个 TU 与另一个调用

foo(nullptr)
的 TU 链接,那么
mov
指令肯定会尝试从
rdi
中的地址读取,这就是
nullptr
编译到的地址,我猜是 0。

这是否意味着分段错误是不可避免的? (我并不是说我想避免 segv,恰恰相反,我只是想知道事情是否会变得如此糟糕,以至于没有 segv 并且程序继续运行,谁知道在哪里!)


(1)我知道取消引用空指针是否是UB的问题仍然没有解决,但这不是我之前的问题的重复。

c++ segmentation-fault undefined-behavior dereference nullptr
1个回答
0
投票

空指针的运行时取消引用是否总是导致分段错误?

不,它只是具有未定义的行为 - 所以它是未定义将会发生什么。

© www.soinside.com 2019 - 2024. All rights reserved.