2011-10-28 83 views
3

这里是我的代码:这是一个gcc优化错误吗?

bool func(const MY_STRUCT *const ptr, some_struct *x, int y) 
{ 
    printf("IN: %p\n", ptr); // ok 
    for (int i = 0; i < y; ++i) { 
     if (ptr->foo(x[i].key) == 0) { 
      return false; 
     } 
    } 
    printf("OUT: %p\n", ptr); // ok 
    return true; 
} 

void process(void) 
{ 
    ... ... 
    for (i = 0; i < num; ++i) { 
     MY_STRUCT *ptr = obj->GetPtr(); // success 
     printf("BEFORE: %p\n", ptr); // ok 
     if (func(ptr, x, y) == false) { 
      continue; 
     } 
     printf("AFTER: %p\n", ptr); // <nil> when compile with -O2 
     printf("%s", ptr->data); // *** segment fault here *** 
    } 
} 

输出:

BEFORE: 0x0612d3fa 
IN: 0x0612d3fa 
OUT: 0x0612d3fa 
AFTER: <nil> 
segment fault 

如果我编译上面的代码用-O0,一切工作正常。 但是,如果我使用-O2编译它,在函数func被调用后,ptr变为NULL

这是一个海湾合作委员会的错误?有没有人遇到类似的错误?

我的gcc版本是:gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)

+0

你可能在'func'中的“做某事”代码中存在一个bug,该代码会捣毁调用者的'ptr' –

+6

也许这是一个编译器的bug,但在开始搜索之前,在valgrind下运行你的程序,确定没有内存访问问题。也许你在某处存在堆栈损坏。 –

+7

这是代码中的99.999%的错误。请发布更多代码和实际用法+执行输出。 –

回答

1

存在(可能)您在func中存在堆栈碎片的可能性,它将覆盖调用者堆栈上的ptr。确保func中的任何数组或结构访问保持在边界内。如果不是因为我对gcc 3.x的回忆,我会说这几乎肯定是实际发生的事情。即便如此,这是最可能的解释。

给你在这一点上,疑点利益,如果你的代码是真的,张贴在你的问题,那么,这可能是一个编译器错误:

printf("BEFORE: %p\n", ptr); // ok 
    if (func(ptr, x, y)) { 
     continue; 
    } 
    printf("AFTER: %p\n", ptr); // <nil> when compile with -O2 

ptr是按值传递到func,所以它的调用函数的值不应该改变,不管在func内发生了什么。

但是,您使用的是真正古老的编译器;即使你报告这个错误,也不会有任何结果。这很可能是因为gcc已经改变了很久以前。尝试更新的版本或不同的编译器。

+0

谢谢。我将尝试稍后使用gcc4编译它并发布结果。奇怪的是'ptr'总是'NULL'。我认为如果'func'中的某个东西重写'ptr'的值,它将是一个随机值,几乎不可能是0。 – iCoder

1

无论错误编译器可能会或可能不会有,如果你看到你发布的代码所描述的问题,那么你的GCC在任何优化级别打破。

根本不应该达到有问题的代码行。

func总是返回true,如果返回true,则会跳过循环体的最后一部分。

如果您怀疑有编译器错误,请先编写一个代码样本来重现它。

当我们不知道你的实际代码是什么样的,我们不可能猜测GCC的行为是否正确。

+0

我假设在'//做些事情'的某个地方有'return false';另一种选择简直太可怕了。 –

+0

很有可能,但是如果我们不知道它在哪里,还有什么可能发生,那么就不可能猜测正确的行为应该是什么 – jalf

+0

哦,绝对。 –