gcc -O3选项会导致警告,而-O2选项不会。

3

我正在构建一个相当复杂的应用程序,使用-O0编译时没有任何错误/警告。但是当我尝试使用-O3时,出现了一些令人困惑的错误。例如:

1: static pinfo_t* pinfo[2] = { &gv1, &gv2 }; // GLOBAL
2: 
3: int i;
4: int x = sizeof(pinfo);
5: 
6: for (i = 0; i < x; i ++)
7:    if (pinfo[i]->id == NO_ID)
8:        printf("%s\n", pinfo[i]->name);

注意,编译器(gcc v4.3.2)使用 -O0(也适用于O1和O2)成功构建了此内容。但是,使用 -O3,编译器正确地将第7行标记为可能导致错误的问题所在的行:
error: array subscript is above array bounds

说得没错,但当我注释掉第7行时,它对第8行没有问题,而第8行也应该被标记出来!

非常感谢您的帮助!


2
过度匿名化了。如果我假设while=for,那么我看到的代码不应该引发错误。 - Joshua
你的 while 循环不正确。了解正在发生的事情的好方法是查看生成的汇编代码。 - Étienne
@Joshua,我看到一个循环访问2 * sizeof(pinfo_t *)pinfo元素的代码。在所有主要(和许多次要)平台上,sizeof(pinfo_t *)都大于1,因此它会越界。 - user395760
1
你的问题存在很多问题。主题中写着“-O2”,但在正文中却写着“-O0”。然后你又问如何注释掉第6行。你真正遇到的情况是什么?你想知道什么? - R.. GitHub STOP HELPING ICE
@Étienne:是的,它似乎也是虚假代码... - R.. GitHub STOP HELPING ICE
显示剩余5条评论
2个回答

8

关于警告和优化级别,在GCC中,当在优化过程中分析代码时,会生成一些警告,因此当这些过程未启用时,这些警告也不会被发出。这是一个长期存在的问题,但迄今为止它还没有在任何人的待办事项列表中得到足够的重视。


天啊,所以如果我想快速编译(-O0),那么我就得不到所有的警告……好吧,这是个好消息。我真的希望 -O2 打开所有的警告,因为我再也不使用 -O3 编译了。 - dave

2
美元对甜甜圈,编译器在 -O3 下完全展开循环,类似于以下内容:
...

if (pinfo[0]->id == NO_ID)
    printf("%s\n", pinfo[0]->name);
if (pinfo[1]->id == NO_ID)
    printf("%s\n", pinfo[1]->name);
if (pinfo[2]->id == NO_ID)
    printf("%s\n", pinfo[2]->name);

...

然后它观察到生成的索引超出了界限,并对此发出警告。


这很有道理,除非注释掉“if”时没有错误。 - user2337373
这并没有说太多。谁知道编译器正在进行什么优化以及它如何处理if语句中的pinfo[i] - Nik Bougalis
啊,也许吧。看起来我得花很长时间来修复代码 :/ - user2337373

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接