使用带有优化的g ++进行编译时出现段错误

时间:2018-09-12 02:04:56

标签: c++ g++ compiler-optimization

在我的代码中(使用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)上进行编译时才发现问题,并且由于多个原因而导致链接错误相同功能的实例。

0 个答案:

没有答案