这是一个gcc优化错误吗?

时间:2011-10-28 10:32:53

标签: c++ gcc gcc3

这是我的代码:

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 bug吗?有没有人遇到类似的错误?

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

2 个答案:

答案 0 :(得分:1)

无论您的编译器可能有或没有任何错误,如果您在发布的代码中看到所描述的问题,那么您的GCC将在任何优化级别被破解。

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

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

如果您怀疑编译器错误,请首先编写一个可以重现它的代码示例。

当我们不知道您的实际代码是什么样的时候,我们无法猜测GCC的行为是否正确。

答案 1 :(得分: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中发生变化。尝试更新版本或不同的编译器。