gpt4 book ai didi

c++ - UB 递增 NULL 指针导致的错误示例

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:07:08 25 4
gpt4 key购买 nike

这段代码:

int *p = nullptr;
p++;

导致未定义的行为,正如在 Is incrementing a null pointer well-defined? 中讨论的那样

但是在向其他人解释为什么他们应该避免使用 UB 时,除了说它不好因为 UB 意味着任何事情都可能发生之外,我还喜欢举一些例子来证明这一点。我有大量用于访问超出限制的数组的方法,但我找不到一个。

我试过了

int testptr(int *p) {
intptr_t ip;
int *p2 = p + 1;
ip = (intptr_t) p2;
if (p == nullptr) {
ip *= 2;
}
else {
ip *= -2;
} return (int) ip;
}

在一个单独的编译单元中希望优化编译器会跳过测试,因为当 p 为 null 时,行 int *p2 = p + 1; 是 UB,并且允许编译器假定代码不包含 UB。

但是 gcc 4.8.2(我没有可用的 gcc 4.9)和 clang 3.4.1 都给出了正值!

有人可以建议一些更聪明的代码或其他优化编译器来在递增空指针时出现问题吗?

最佳答案

这个例子怎么样:

int main(int argc, char* argv[])
{
int a[] = { 111, 222 };

int *p = (argc > 1) ? &a[0] : nullptr;
p++;
p--;

return (p == nullptr);
}

从表面上看,这段代码说:'如果有任何命令行参数,初始化 p 以指向 a[] 的第一个成员,否则初始化它为空。然后递增它,然后递减它,并告诉我它是否为空。”

从表面上看,如果我们提供命令行参数,这应该返回“0”(表示 p 非空),如果我们不提供,则返回“1”(表示空) .请注意,我们绝不会取消引用 p,如果我们提供参数,则 p 始终指向 a[] 的范围内。

使用命令行 clang -S --std=c++11 -O2 nulltest.cpp (Cygwin clang 3.5.1) 编译生成以下代码:

    .text
.def main;
.scl 2;
.type 32;
.endef
.globl main
.align 16, 0x90
main: # @main
.Ltmp0:
.seh_proc main
# BB#0:
pushq %rbp
.Ltmp1:
.seh_pushreg 5
movq %rsp, %rbp
.Ltmp2:
.seh_setframe 5, 0
.Ltmp3:
.seh_endprologue
callq __main
xorl %eax, %eax
popq %rbp
retq
.Leh_func_end0:
.Ltmp4:
.seh_endproc

此代码表示“返回 0”。它甚至懒得检查命令行参数的数量。

(有趣的是,注释掉减量对生成的代码没有影响。)

关于c++ - UB 递增 NULL 指针导致的错误示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29845131/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com