这是 gcc 优化错误吗?

发布于 2024-12-12 13:15:27 字数 1028 浏览 0 评论 0原文

这是我的代码:

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

Here's my code:

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 ***
    }
}

output:

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

If I compile above code with -O0, everything works fine.
However, if I compile it with -O2, after the function func is called, the ptr become NULL!

Is this a gcc bug? Did anyone ever have encountered similar bug?

My gcc version is: gcc version 3.4.5 20051201 (Red Hat 3.4.5-2)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心房的律动 2024-12-19 13:15:27

(很可能)您在 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被传递value 为 func,因此无论 func 内发生什么,调用函数中的值都不应更改。

然而,您使用的是真正古老的编译器;即使您报告此错误,也不会产生任何结果。很可能导致这种情况的原因早已在 gcc 中发生了变化。尝试更新版本或不同的编译器。

There is the (likely) possibility that you have a stack-smasher in func, which is overwriting ptr on the caller's stack. Make sure any array or structure accesses in func remain in bounds. If it weren't for my sour memories of gcc 3.x, I would say that this is nearly certainly what's actually going on. Even so, this is the most likely explanation.

Giving you the benefit of the doubt on that point, if your code is really as posted in your question, then yes, this may be a compiler bug:

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

ptr is passed by value to func, so it's value in the calling function should not change, regardless of what happens within func.

However, you're using a truly ancient compiler; even if you report this bug, nothing will ever come of it. It is quite likely that whatever caused this has long since changed in gcc. Try a newer version or a different compiler.

笑红尘 2024-12-19 13:15:27

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

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

func 始终返回 true,如果返回 true,则跳过循环体的最后部分。

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

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

Whatever bugs your compiler may or may not have, if you see the described problem in the code you posted, then your GCC is broken at any optimization level.

The problematic line of code should never be reached at all.

func always returns true, and if it returns true, the last part of the loop body is skipped.

If you suspect a compiler bug, start by writing a code sample that reproduces it.

When we don't know what your actual code looks like, it's impossible for us to guess at whether GCC's behavior is correct or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文