由UB递增NULL指针引起的错误示例 [英] Example of error caused by UB of incrementing a NULL pointer

查看:86
本文介绍了由UB递增NULL指针引起的错误示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码:

int *p = nullptr;
p++;

引起未定义的行为,如是否在递增定义明确的空指针?

cause undefined behaviour as it was discussed in Is incrementing a null pointer well-defined?

但是在向同伴解释为什么他们应该避免使用UB的同时,说它不好因为UB意味着任何事情都可能发生,所以我想举一些例子来演示它。我有很多可以访问超出限制的数组,但是我找不到一个。

But when explaining fellows why they should avoid UB, besides saying it is bad because UB means that anything could happen, I like to have some example demonstating it. I have tons of them for access to an array past the limits but I could not find a single one for that.

我什至尝试

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 为空,行 int * p2 = p + 1; 为UB,允许编译器假定代码

in a separate compilation unit hoping that an optimizing compiler would skip the test because when p is null, line int *p2 = p + 1; is UB, and compilers are allowed to assume that code does not contain UB.

但是gcc 4.8.2(我没有可用的gcc 4.9)和clang 3.4.1都回答一个正值!

But gcc 4.8.2 (I have no useable gcc 4.9) and clang 3.4.1 both answer a positive value !

有人会建议一些更聪明的代码或另一个优化的编译器在增加空指针时出现问题吗?

Could someone suggest some more clever code or another optimizing compiler to exhibit a problem when incrementing a null pointer ?

推荐答案

这个例子怎么样:

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

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

    return (p == nullptr);
}

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

At face value, this code says: 'If there are any command line arguments, initialise p to point to the first member of a[], otherwise initialise it to null. Then increment it, then decrement it, and tell me if it's null.'

表面上它应该返回'0'(表示 p 为非null)(如果我们提供命令行参数),否则为'1'(表示null)。
请注意,我们绝不会取消引用 p ,并且如果我们提供参数,则 p 总是指向在 a [] 的范围内。

On the face of it this should return '0' (indicating p is non-null) if we supply a command line argument, and '1' (indicating null) if we don't. Note that at no point do we dereference p, and if we supply an argument then p always points within the bounds of a[].

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

Compiling with the command line clang -S --std=c++11 -O2 nulltest.cpp (Cygwin clang 3.5.1) yields the following generated code:

    .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。甚至不必费心检查命令行参数的数量。

This code says 'return 0'. It doesn't even bother to check the number of command line args.

(有趣的是,注释说明减量对无效生成的代码。)

(And interestingly, commenting out the decrement has no effect on the generated code.)

这篇关于由UB递增NULL指针引起的错误示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆