在我的代码中(使用g ++ 7.3版)我发生了一个非常奇怪的崩溃:
使用-o0进行编译时,一切正常。但是,当使用-O1 / O2 / O3进行编译时,出现了段错误。在GDB中运行,看起来像从函数返回后一样,出于某种原因,存在对_unwind_resume的调用,它会导致段错误。在用-O0编译的代码中,我没有在同一位置看到对_unwind_resume的任何调用。
但是还有更多:
我尝试使用valgrind运行它,以查看是否获得了任何有用的信息。它报告“地址处无法识别的指令”,但没有内存问题。
我尝试单独使用不同的优化标志,以查看是否存在导致此问题的特定优化。我使用了g ++ -Q -O1 -help = optimizers列出的所有优化。没有崩溃。我试图一起使用所有相关的-f标志。仍然没有崩溃。
我尝试了使用clang ++而不是g ++进行任何优化级别的编译。再次,可以正常运行而不会崩溃。
我猜想调用栈在某种程度上会因为g ++中的优化代码而损坏,但是我不知道为什么或要这样做。知道如何处理吗?
注意:很遗憾,我无法共享代码,无论如何在这里共享它太大了。
编辑:我设法减少了导致错误的代码。这是一个复制器:
#include <iostream>
#include <vector>
using namespace std;
class Expr;
typedef std::vector<Expr*> ExprVec;
enum class Ops {
Search
};
enum class ExprKind {
Const,
Function,
Unknown
};
namespace Values {
class Value
{
public:
virtual ~Value() {};
};
class String : public Value
{
public:
String(const string& v): _val(v) {}
String(const char* s): _val(s) {}
~String() {
}
static const string name;
private:
string _val;
};
const string String::name = "String";
} // Values
class Expr
{
public:
Expr() {}
Expr(const ExprVec& args)
: _args(args) {}
virtual ~Expr() {
for (auto arg: _args) {
delete arg;
}
};
virtual Values::Value* run() = 0;
protected:
ExprVec _args;
};
template<class ValType>
class ConstExpr: public Expr
{
public:
ConstExpr() {}
ConstExpr(ValType* val)
: _val(val) {}
~ConstExpr() {
delete _val;
}
virtual Values::Value* run() {
return _val;
}
private:
ValType* _val;
};
typedef ConstExpr<Values::String> StringExpr;
// This is a template for all expression nodes. Instantiate for each expression
template <ExprKind Kind, Ops Name, class RetVal, class Arg1>
class ExprT: public Expr
{
public:
ExprT() {}
ExprT(const ExprVec& args)
: Expr(args) {}
virtual Values::Value* run() {
Arg1* arg1= dynamic_cast<Arg1*>(_args[0]->run());
return run(arg1);
}
RetVal* run(Arg1* arg1);
};
typedef ExprT<ExprKind::Function, Ops::Search, Values::String, Values::String> Search;
template<>
Values::String* Search::run(Values::String* arg1)
{
}
int main()
{
Values::String* str = new Values::String("blahbla");
Expr* se = new StringExpr(str);
ExprVec args({se});
Expr* search = new Search(args);
search->run();
cout<<"Done\n";
return 0;
}
Edit2:我只是意识到这不是一个实际的复制器。 Search :: run在这里不返回任何值,在原始代码中,它确实返回一个值。我将尝试创建一个更好的复制器。
更新: 我终于弄清楚了...上面的示例无法重现特定的错误,因为它至少需要两个源文件和一个头文件。问题是,我在头文件中有一些带有非专业模板定义的函数,并且在一个源文件中具有这些函数的完全专业化的模板实例化。
我没有在包含文件中声明专业化,这是问题的根源...我只是在尝试在Windows(而不是Linux)上进行编译时才发现问题,并且由于多个原因而导致链接错误相同功能的实例。