首先,我两个月前才开始编程 C/C++(但在 Java 方面有更多经验),所以我对 C/C++ 的经验还很远。我正在写一篇论文,并且正在使用/扩展为之前的研究而编写的其他代码。
现在,这个错误绝对是我遇到过的最奇怪的错误,我花了将近 3 个小时才找到并缩小到我可以重现它的最基本形式。最后,我有这两个文件,代码如下
c.hh:
#ifndef C_HH_
#define C_HH_
class complex {
public:
double re;
};
#endif
测试.cc:
#include <iostream>
#include "c.hh"
int main(int argc, char **argv) {
complex* c;
c->re = 0.0;
for (int i = 0; i < 3; ++i) {
c->re = (c->re) + (i==1)?0:1;
}
std::cout << c->re;
}
我唯一可以取出并且仍然会发生错误的是c.re的初始化,即“c->re = 0.0;”。但是,我把它留在里面是因为即使我删除了代码的下部,如果没有这一行,错误仍然会发生,因为 c.re 还没有被初始化(或者我认为?)。
我发现重现错误所必需的所有其他内容,即
1)for循环。如果 i=1,2,3 的行分开写,不会导致错误。
2)我的极限!例如,如果 i 仅从 0 运行到 2,则不会导致错误。仅在至少 3 次迭代后发生。
3)显式赋值“c->re = (c->re)+”,用“+=”代替“=(c->re)+”不会报错。
4) i "(i==1)?0:1" 的评估和(!)条件检查。使用 if(..) 执行此操作也会导致错误,但如果不使用 i 或不执行条件检查,则不会导致错误。
5) c.re.的输出 即“std::cout << c->re;”。简单地评估 c.re ("c->re;") 不会导致错误。如果只有一个输出而根本没有评估 c.re,它也不会导致错误。通过 "fprintf(stdout, "%d", c->-re);" 做同样的事情 也会导致错误。
同样非常重要的是,只有当我像这样编译代码时才会发生错误:
g++ -O3 -c -o test.o test.cc
g++ -O3 -o test test.o c.hh
如果省略“-O3”,它不会导致错误,所以我认为这是代码产生这个对我来说难以理解的错误的真正原因。请注意,使用 -O3 是因为正如我提到的,此代码是为研究编写的,此类函数可能会被调用多达数百万次,因此最好尽可能优化。然而,我只是根据给我的内容改编了这个“约定”,并不真正了解细节以及使用或不使用它的确切结果是什么。
最重要的是,无论何时导致错误,程序都不会运行。意思是,即使我将任何形式的输出放在任何地方,即使在代码的第一行,运行“测试”也会立即导致错误并且不输出任何内容。
最后,我在尝试执行程序“test”时遇到的错误如下:
0 [main] test 10720 cygwin_exception::open_stackdumpfile: Dumping stack trace to test.exe.stackdump
其中 stackdump 文件包含以下内容:
Exception: STATUS_ACCESS_VIOLATION at eip=00401770
eax=00000001 ebx=0028CC8C ecx=8001801F edx=00000000 esi=0028CCA0 edi=0028CCA4
ebp=0028CC68 esp=0028CC50 program=D:\somepath\test\src\test.exe, pid 13768, thread main
cs=0023 ds=002B es=002B fs=0053 gs=002B ss=002B
Stack trace:
Frame Function Args
0028CC68 00401770 (00000001, 0028CC8C, 800280E8, 61007D35)
0028CD28 61007D9A (00000000, 0028CD84, 61006DC0, 00000000)
End of stack trace
正如您可能会说的那样,我对这个问题非常迷茫并且不知道发生了什么,因为似乎没有任何编程“逻辑”的原因来解释为什么会发生这种情况。在这个非常简单的代码中我做错了什么吗?无论如何要“解决”这个问题而不必忽略 -O3 优化?或者这可能不那么重要?
我希望我提供了足够的信息,感谢您的帮助!