使用 GCC 4.4.7 和 LLVM 6.1 编译时,以下代码似乎可以正确执行。但我认为它不能正确编译 gcc 版本 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)。
以下是我将问题简化为:
#include <stdio.h>
#include <stdlib.h>
#define GENERAL 1
#define BRACKETS 2
#define QUOTES 3
//This method contains the issue.
void foo(char *qb, char* into) {
//The starting state is important for the bug.
int state = QUOTES;
int save_state = BRACKETS;
//This here needs to reference qb in some way, previously I
//had this as just qb however I will set it to qb[0]. Note that this
//is a contrived example, I already know that setting it to one
//makes this pass which makes me suspect this is a compiler
//issue.
while (qb[0]) {
printf("State is %d\n", state);
switch (state) {
case BRACKETS:
printf("Yay this was correctly executed\n");
exit(0);
break;
case GENERAL:
printf("Oh no how did you get here?\n");
printf("State is %d\n", state);
exit(1);
break;
case QUOTES:
state = save_state;
printf("State went to %d btw BRACKETS is %d\n", state, BRACKETS);
save_state = GENERAL; //Remove this line and it will work even
when optimised.
printf("After save state, state went to %d btw BRACKETS is
%d\n", state, BRACKETS);
break;
default: ;
}
printf("State %d btw GENERAL %d\n", state, GENERAL);
}
printf("If you see this then something is really wrong.\n");
exit(4);
}
int main() {
//These don't seem to matter don't concern yourself with them.
char *b = "123";
char out[4];
foo(b, out);
return 1;
}
如果我编译它: gcc -O0 -g -Wall -Werror sillyswitch.c -o sillyswitch
它会打印
Yay this was correctly executed
这是我期望它打印的
但是,如果我使用以下命令编译它: gcc -O -g -Wall -Werror sillyswitch.c -o sillyswitch
它会打印
Oh no how did you get here?
这不是我期望看到的。
我不明白为什么打开优化后它不能按预期工作。代码错误是因为在第二个循环中采用的 switch 语句的分支是任意的吗?因为它是C,我是否以某种方式射中了自己的脚?
完整输出失败:
State is 3
State went to 2 btw BRACKETS is 2
After save state, state went to 2 btw BRACKETS is 2
State 2 btw GENERAL 1
State is 2
Oh no how did you get here?
State is 1
成功完整输出:
State is 3
State went to 2 btw BRACKETS is 2
After save state, state went to 2 btw BRACKETS is 2
State 2 btw GENERAL 1
State is 2
Yay this was correctly executed