从 Null 指针加载,为什么这不会使我的程序崩溃?

Loading from a Null pointer, why doesn't this crash my program?

我这里有这段代码。它似乎在取消引用一个空指针,但是当我编译并 运行 它时,它并没有崩溃!这里没有生成分段错误。 @dx.nothing 定义为 0。稍后,应用程序 load 从该内存位置获取一个值,即 i32*。所以看起来应用程序正在取消引用空指针。不过,这似乎不是问题。

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@dx.nothing = internal constant i32 0

define i32 @main() {
    %1 = load i32, i32* @dx.nothing
    %2 = load i32, i32* @dx.nothing
    %3 = load i32, i32* @dx.nothing
    %4 = fmul fast float 5.000000e-01, 5.000000e-01
    %5 = fmul fast float 0x3FC99999A0000000, 5.000000e-01
    %6 = fmul fast float 0x3FECCCCCC0000000, 5.000000e-01
    %7 = fmul fast float 1.000000e+00, 5.000000e-01
    %8 = load i32, i32* @dx.nothing
    %9 = load i32, i32* @dx.nothing
    %10 = load i32, i32* @dx.nothing

    ret i32 0
}

算了,我把这道题搞砸了。我读错了代码。 我发现这一行实际上并没有创建空指针。相反,它创建了一个值为 i32 0

的全局常量
@dx.nothing = internal constant i32 0

然后当应用程序稍后尝试加载该值时,它会加载 i32 0 in.

考虑以下示例:

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@stuff1 = internal constant i32 5

define i32 @main() {
    %1 = load i32, i32* @stuff1
    ret i32 %1
}

此代码创建一个全局常量,其值为 i32 5load 将该值存入虚拟寄存器 %1,然后 returns。因此 5 作为 @main 函数的退出代码返回。

如果您要编译 运行 这个示例代码:

$ llvm-as code.ll -o code.bc
$ lli code.bc
$ echo $?
5