我不确定我是否在g(4.4.1-4ubuntu9)中发现了一个错误,或者我是否正在做
有问题.我相信我所看到的是启用引入的错误
使用g -O2进行优化.我试图将代码提炼到只有
相关部分.
启用优化后,我有一个失败的ASSERT.什么时候
优化被禁用,相同的ASSERT不会失败.我想我已经跟踪了
它归结为一个函数及其调用者的优化.
系统
>语言:C
> Ubuntu 9.10
> g -4.4.real(Ubuntu 4.4.1-4ubuntu9)4.4.1
> Linux 2.6.31-22-server x86_64
优化已启用
编译对象:
g -DHAVE_CONFIG_H -I. -fPIC -g -O2 -MT file.o -MD -MP -MF .deps / file.Tpo -c -o file.o file.cpp
这是来自objdump -dg file.o的相关代码.
00000000000018b0
优化已禁用
现编译:
g -DHAVE_CONFIG_H -I. -fPIC -g -O0 -MT file.o -MD -MP -MF .deps / file.Tpo -c -o file.o file.cpp
0000000000008d27
原始C代码
这是原始C的消毒版本.我刚刚更改了一些名字
并删除了不相关的代码.原谅我的偏执,我只是不想暴露
来自未发表和未发布的工作的代码太多:-).
static void helper_function(my_struct_t *e,int *outArr)
{
unsigned char event_type = e->header.type;
if (event_type == event_A || event_type == event_B) {
outArr[0] = action_one;
} else if (event_type == event_C) {
outArr[0] = action_one;
outArr[1] = action_two;
} else if (...) { ... }
}
static void buggy_invoker(my_struct_t *e,predicate_t pred)
{
// MAX_ACTIONS is #defined to 5
int action_array[MAX_ACTIONS] = {0};
helper_function(e,action_array);
...
}
static int has_any_actions(my_struct_t *e)
{
int actions[MAX_ACTIONS] = {0};
helper_function(e,actions);
return actions[0] != 0;
}
// *** ENTRY POINT to this code is this function (note not static).
void perfectly_fine_invoker(my_struct_t e,predicate_t pred)
{
memfence();
if (has_any_actions(&e)) {
buggy_invoker(&e,pred);
}
...
}
如果您认为我已经过度混淆或消除了太多,请告诉我.用户
这段代码叫’perfect_fine_invoker’.通过优化,g优化了
‘has_any_actions’函数可直接调用’helper_function’,即
你可以在装配中看到.
问题
所以,我的问题是,对任何人来说,它看起来像一个错误的优化吗?
如果它有用,我可以发布原始C代码的消毒版本.
这是我第一次发布Stack Overflow,所以如果我能做的话请告诉我
任何使问题更清晰或提供任何其他信息的事情.
答案
编辑(事后几天):
我在下面接受了我的问题的答案 – 这不是g中的优化错误,我只是看错了汇编代码.
但是,对于将来可能会看到这个问题的人,我找到了答案.我在C(http://blog.regehr.org/archives/213和http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html)中对未定义的行为进行了一些阅读,并且编译器的一些描述使用未定义的行为优化掉函数似乎非常熟悉.
我在函数’helper_function’中添加了一些NULL指针检查,并且看到…… bug消失了.我应该开始使用NULL指针检查,但显然没有让它们允许g做任何想做的事情(在我的情况下,优化掉调用).
希望这些信息有助于未来的人.
如果查看未优化的版本,它会在此行保存%rdi寄存器
9498: 48 89 bd 38 fe ff ff mov %rdi,-0x1c8(%rbp)
…然后在调用helper_function之前,它将保存的值移动到移动到%rdi的%rax中.
94c1: 48 8b 85 38 fe ff ff mov -0x1c8(%rbp),%rax
94c8: 48 89 d6 mov %rdx,%rsi
94cb: 48 89 c7 mov %rax,%rdi
在优化它时,编译器就可以摆脱所有来回移动.