3

这是我的代码:

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 版本是:gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)

4

2 回答 2

1

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

根本不应该触及有问题的代码行。

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

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

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

于 2011-10-28T12:40:19.387 回答
1

(可能)您有一个堆栈粉碎器 in 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。尝试更新版本或不同的编译器。

于 2011-10-28T12:40:58.403 回答