启用优化时的g ++分段错误

Posted

技术标签:

【中文标题】启用优化时的g ++分段错误【英文标题】:g++ segmentation fault when enabling optimization 【发布时间】:2013-12-09 17:21:16 【问题描述】:

当我启用优化(标志 -O2/-03)时,为什么这段代码会产生分段错误。 在return前加上assert,就OK了。

#include <iostream>
#include <typeinfo>
#include <vector>
#include <assert.h>


struct doublet 

    doublet(double val1 = 0, double val2 = 0) 
        dob[0] = val1;
        dob[1] = val2;
    

    template< class Expr >
    doublet& operator=(Expr const& x)
        dob[0] = x[0];
        dob[1] = x[1];
        return *this;
    

    const double&  operator[](unsigned ix) const  
      /*
       * BUG HERE
       */
      //assert(ix<2);
      return dob[ix];
    


    void print()
        std::cout << (*this)[0] << std::endl;
        std::cout << (*this)[1] << std::endl;
    
private:
      double dob[2];
;

struct plus 

    static double  apply( double a,  double b)  
        return a + b;
    
;

struct minus 

      static double  apply(double a, double b)
        return a - b;
    
;



template <class L, class OpTag, class R>
struct Expression 

    Expression (L const& l, R const& r) :l(l),r(r)

    L const& l;
    R const& r;

    typedef const double result_type;

    result_type operator[](unsigned ix) const 
        return  OpTag::apply(l[ix],r[ix]);
    

;

template <class L, class R>
Expression<L,plus,R> operator+(L const& l, R const& r)
    return Expression<L,plus,R>(l,r);


template <class L, class R>
Expression<L,minus,R> operator-(L const& l, R const& r)
    return Expression<L,minus,R>(l,r);


int main()

    doublet a(4.0,1.0), b(5.1,3.3), c(7.4,5.2);

    Expression<Expression<doublet, plus, doublet>, plus, doublet> 
    k = b + a + c;
    std::cout << k[0] << " " << k[1] << std::endl;


Assembler instructions 到此代码。第 20 行 (edx=0) 出现分段错误。

更新。我会弄清楚有什么问题。为了稳定工作需要将 k 声明为 doublet 或添加到 Expression 类 operator=L const& 的情况是不对的,因为它会创建模板对象(Herb Sutter 关于 const 对右值的引用)。

【问题讨论】:

哪个编译器? g++ 4.8.1 编译这个很好 【参考方案1】:

这是错误的:

Expression (L const& l, R const& r) :l(l),r(r)

L const& l;

您通过引用绑定l。然后在你的使用中:

Expression<Expression<doublet, plus, doublet>, plus, doublet> 
    k = b + a + c;

b + a 创建一个临时的,但它只存在到语句结束。在下一行中,k.l 是一个悬空引用。

【讨论】:

是的 - 我欢迎传递对 const 的引用,其中该引用不是临时数组! 是的,它有效。那么就我而言,它一定不起作用。为什么我的案例适用于 assert? @crastinus:未定义的行为 @crastinus 欢迎来到未定义行为的世界。有时即使程序无效,事情也可能看起来有效(这可能是因为临时使用的空间没有被重用)。然后,代码或编译器标志中看似不重要的微小变化可能会再次失败。

以上是关于启用优化时的g ++分段错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 CUDA 流时的段错误

推送到成员向量时的段错误

g_slist_copy_deep 返回分段错误

线程示例,分段错误

对向量使用 Push Back 功能时的分段错误

为啥写作主要;在 C 中给出一个段错误