这是 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版本是: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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
(很可能)您在
func
中存在堆栈粉碎器,它会覆盖调用者堆栈上的ptr
。确保func
中的任何数组或结构访问均保持在边界内。如果不是因为我对 gcc 3.x 的痛苦回忆,我会说这几乎肯定是实际发生的事情。即便如此,这也是最有可能的解释。在这一点上给你一个怀疑的好处,如果你的代码确实如你的问题中发布的那样,那么是的,这可能是一个编译器错误:
ptr
被传递value 为func
,因此无论func
内发生什么,调用函数中的值都不应更改。然而,您使用的是真正古老的编译器;即使您报告此错误,也不会产生任何结果。很可能导致这种情况的原因早已在
gcc
中发生了变化。尝试更新版本或不同的编译器。There is the (likely) possibility that you have a stack-smasher in
func
, which is overwritingptr
on the caller's stack. Make sure any array or structure accesses infunc
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:
ptr
is passed by value tofunc
, so it's value in the calling function should not change, regardless of what happens withinfunc
.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.无论您的编译器可能有或没有错误,如果您在发布的代码中看到所描述的问题,那么您的 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.