UB在操作nullptr时

时间:2015-05-20 12:48:22

标签: c++ pointers

这是围绕Example of error caused by UB of incrementing a NULL pointer

的讨论的相关问题

假设我定义了这个数据结构:

union UPtrMem
{
    void* p;
    char ach[sizeof(void*)];
}

UPtrMem u;
u.p = nullptr;
u.p++;      // UB according to standards
u.ach[0]++; // why is this OK then??

pach共享相同的内存,因此仅仅是修改内存位置(恰好包含指针)UB的行为?一旦你试图取消引用指针,我认为它只会被取消定义。

4 个答案:

答案 0 :(得分:10)

这仍然是UB,因为

  

从未最近编写的联盟成员中读取未定义的行为。

(来自here)。所以你有UB,无论p的价值如何。总结:

  

为什么这样呢?

不是。

答案 1 :(得分:1)

标准使null指针未定义递增的原因是因为并不总是null指针包含像{{1}这样具有算术意义的值。 }}。它可以包含一个特定的位模式,指示0的不可寻址内存。

你的例子也有其他问题。

当你增加一个已分配的指针时,它会将它指向的东西的大小添加到它的值。

因此,在CPU计算机上32bit可能会在向int*添加4时提前sizeof(int)个位置。

1的问题是编译器没有大小信息,因此无法知道增加其值的距离。

你的示例中,您可以执行以下操作:

void*

根本不会增加指针,它会增加char数组的第一个元素中包含的u.ach[0]++; 值。当然,这是未定义的,即使它有效,也不能依赖它具有任何特定价值。

答案 2 :(得分:1)

你的例子不包含任何UB,因为你没有那么远:它是无法编译的无效代码。

要想拥有你正在考虑的那种UB,标题是“操纵nullptr时的UB”,你需要让代码执行

当它不编译时就不会发生。

以防万一我的答案后问题发生了变化,这种情况对于这些明显设计到陷阱的响应者问题并不少见,这就是我写这篇文章所呈现的代码:

union UPtrMem
{
    void* p;
    char ach[sizeof(void*)];
}

UPtrMem u;
u.p = nullptr;
u.p++;      // UB according to standards
u.ach[0]++; // why is this OK then??

增加void*只是无效,不是受支持的操作,也不会编译。

答案 3 :(得分:-3)

似乎我u.p++;甚至没有效果,因为void没有大小,所以没有任何增加。但是u.ach[0]++;是有效的,因为你增加了一个字符。

编辑是的,它占用了结构中的空间......但是它指向的内容没有大小...它会增加什么?