是在一个空指针未定义行为执行算术? [英] Is performing arithmetic on a null pointer undefined behavior?

查看:180
本文介绍了是在一个空指针未定义行为执行算术?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我看来像下面的程序计算了无效的指针,因为 NULL 是没有良好的任何东西,但赋值和比较平等:

It looks to me like the following program computes an invalid pointer, since NULL is no good for anything but assignment and comparison for equality:

#include <stdlib.h>
#include <stdio.h>

int main() {

  char *c = NULL;
  c--;

  printf("c: %p\n", c);

  return 0;
}

不过,好像没有针对未定义的行为在GCC或锵警告或仪器仪表的说,这其实是在UB。是算术实际上是有效的,我太迂腐,或者这是在他们的检查机制的缺陷,我应该报告?

However, it seems like none of the warnings or instrumentations in GCC or Clang targeted at undefined behavior say that this is in fact UB. Is that arithmetic actually valid and I'm being too pedantic, or is this a deficiency in their checking mechanisms that I should report?

测试:

$ clang-3.3 -Weverything -g -O0 -fsanitize=undefined -fsanitize=null -fsanitize=address offsetnull.c -o offsetnull
$ ./offsetnull
c: 0xffffffffffffffff

$ gcc-4.8 -g -O0 -fsanitize=address offsetnull.c -o offsetnull
$ ./offsetnull 
c: 0xffffffffffffffff

这似乎是有据可查的AddressSanitizer 13759锵和GCC是更侧重于坏的指针解引用,所以这是很公平pretty。但其他检查不抓住它可以: - /

It seems to be pretty well documented that AddressSanitizer as used by Clang and GCC is more focused on dereference of bad pointers, so that's fair enough. But the other checks don't catch it either :-/

修改:那我问这个问题的是, -fsanitize 标记使部分原因动态的检查精心definedness在生成code。这是不是他们应该抓?

Edit: part of the reason that I asked this question is that the -fsanitize flags enable dynamic checks of well-definedness in the generated code. Is this something they should have caught?

推荐答案

这是一个指针没有指向数组指针运算是不确定的行为。结果
此外,取消对NULL指针是不确定的行为。

Pointer arithmetic on a pointer not pointing to an array is Undefined behavior.
Also, Dereferencing a NULL pointer is undefined behavior.

char *c = NULL;
c--;

是不确定的,因为定义的行为ç不指向数组。

C ++ 11标准5.7.5:

当具有整体式的前pression加到或从一个指针中减去,其结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且阵列足够大,结果指向一个元件从原始元件偏移,使得所得到的和原始的数组元素的下标之差等于积分前pression。换言之,如果前pression P指向数组对象的第i个元素,前pressions(P)+ N(等效地,N +(P))和(P)-N(这里N的值n)指向,分别第i + n个和我 - 阵列对象的第n个元素,提供它们的存在。此外,如果前pression p指向数组对象的最后一个元素,前pression(P)+1点中的一个过去的数组对象的最后一个元素,如果前pression Q点中的一个过去的数组对象的最后一个元素,前pression(Q)-1指向数组对象的最后一个元素。如果这两个指针操作数和结果指向相同的数组对象的元素,或者一个过去
  数组对象的最后一个元素,该评估也不得产生溢出;否则,行为是不确定的。

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i + n-th and i − n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

这篇关于是在一个空指针未定义行为执行算术?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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