为什么GCC在这个例子中没有提出警告 [英] Why doesn't GCC throw a warning in this example

查看:308
本文介绍了为什么GCC在这个例子中没有提出警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

启用 -Wsequence-point 后,当未定义的行为代码被发现时,GCC应警告用户。例如

  b = a + ++ a; 

应该被GCC注意到并且应该被报告为未定义行为代码(因为ISO C doesn' t

然而,我玩的是语法,我试过这个:

  int * a = malloc(sizeof(int)* 2); 
a [0] = 1;
printf(%d \\\
,*(a +(* a)++ - * a));

当然,我收到警告


警告:对'* a'的操作可能是未定义的[-W序列点]

即我所期望的,因为 * a (它是 a [0] )的值可能会增加或可能不会增加在处理第三个操作数时。但是,我尝试了以下方法:

  int * a = malloc(sizeof(int)* 2); 
a [0] = 1;
printf(%d \\\
,*(a +(* a)++ - 1));

我很惊讶,因为我没有收到警告。这不应该是UB吗?我的意思是,根据ISO C99,可以在表达评估(除了逗号运算符和三元运算符除外)的任何点评估后增量操作。在我后面的例子中,我不是递增指针,而是指向它的整数。因此,根据标准,它可以随时增加(这意味着它可以在整个表达式被评估后递增),所以程序可以打印 1 2 ,对吗?

为什么GCC不会引发任何警告?或者我错过了什么?我是否错误地理解了规范?

解决方案

gcc的静态分析工具不处理这种情况。 b

对于gcc的静态分析,表达式 *(a +(* a)++ - x)太难了,因为它导致未定义在某些非常特殊的情况下 - 即当 * a 包含 x 时,由于缺乏顺序点而导致的行为。这是当(* a)++ - x 撤销彼此时,所以整体表达式等价于 * a 加上一些副作用。

为了让gcc代码分析发现这个错误,编译器必须跟踪 * a 在其整个生命周期中。尽管在你的例子中它看起来很简单,但是一个更复杂的程序,比如用户输入的数据被读入 a ,这样的分析是不可能的。


With -Wsequence-point enabled, GCC should warn user when undefined behavior code is spotted. For example

b = a + ++a;

should be noticed by GCC and should be reported as "undefined behavior" code (because ISO C doesn't specify the order of evaluating operands for addition).

However, I played with the syntax and I tried this one:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - *a));

Of course, I got the warning

warning: operation on '*a' may be undefined [-Wsequence-point]

which is what I expected, because the value of *a (which is a[0]) may be incremented or may not be while processing the third operand. But, I tried the following one:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - 1));

I was surprised because I got no warnings. Shouldn't this be UB too? I mean, according to ISO C99, post increment operation may be evaluated at any point durring expression evaluation (except for comma operators and ternary operators). In my latter example, I am not incrementing pointer, but instead the integer it points to. So, accordning to the standard, it can be incremented at any point (which means that it can be incremented after whole expression is evaluated), so the program may print both 1 or 2, right?

Why doesn't GCC throw any warnings? Or did I miss something? Did I wrongly understand the specs?

解决方案

Static analysis tool of gcc does not handle this situation.

The expression *(a + (*a)++ - x) is too hard for static analysis of gcc, because it results in undefined behavior due to lack of sequence point under some very specific circumstances - namely, when *a contains x. This is when (*a)++ - x "undo" each other, so overall expression becomes equivalent to *a plus some side effects.

In order for gcc code analysis to spot this error, the compiler must track the content of *a throughout its lifetime. Although it looks simple in your example, a more complex program, say, where data is read into a from user input, renders such analysis impossible.

这篇关于为什么GCC在这个例子中没有提出警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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