从Eigen :: CwiseBinaryOp转换到MatrixXd导致segfault [英] cast from Eigen::CwiseBinaryOp to MatrixXd causes segfault

查看:706
本文介绍了从Eigen :: CwiseBinaryOp转换到MatrixXd导致segfault的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个库,存储Eigen表达式模板作为成员变量,以进行需要做的复杂计算。但是,似乎我不能存储或返回这些表达式模板,除非它们直接在MatrixXd或类似的转换。这迫使每一步都被保存到一个临时的,并且浪费整个设计的效率。



这里有一个简短的例子,导致麻烦。 Holder只是拥有一个Eigen矩阵,而Summer需要两个持有者并输出他们持有的两个矩阵的总和,当你调用get()。



包含文件










b $ b

  #ifndef PB_SIMPLE_H 
#define PB_SIMPLE_H

#include< Eigen / Dense>

template< class EigenType>
class Holder {
public:
typedef EigenType result_type;

private:
result_type in_;

public:
Holder(const EigenType& in):in_(in){}
result_type get()const {return in_; }
};

template< class HoldLeft,HoldRight class>
class Summer {
public:
typedef const typename Eigen :: CwiseBinaryOp<
Eigen :: internal :: scalar_sum_op< double>,
const typename HoldLeft :: result_type,
const typename HoldRight :: result_type> result_type;
// typedef Eigen :: MatrixXd result_type;
private:
HoldLeft left_;
HoldRight right_;

public:
Summer(const HoldLeft& left,const HoldRight& right)
:left_(left),right_(right){}

result_type get()const {return left_.get()+ right_.get(); }
};

typedef Holder< Eigen :: MatrixXd>矩阵
typedef Summer< MatrixHolder,MatrixHolder> MatrixSummer;

#endif / * PB_SIMPLE_H * /

简单测试

  #includePbSimple.h

#include< Eigen / Dense>

int main(int,char * []){
const unsigned int szx = 10,szy = 3;
Eigen :: MatrixXd x(Eigen :: MatrixXd :: Constant(szx,szy,1));
MatrixHolder vx(x);
Eigen :: MatrixXd y(Eigen :: MatrixXd :: Constant(szx,szy,2));
MatrixHolder vy(y);
MatrixSummer vsum(vx,vy);
auto expr = vsum.get();
MatrixHolder vz(expr); //将求和结果强制转换为新的矩阵,在这里失败
return 0;
}




  • 在包含文件中,如果使用

  • 我怀疑这个问题是由于一个悬挂的引用,但不能证明它。

解决方案

这是因为 Holder :: get 返回一个矩阵的副本。然后,这个临时变量作为const引用存储为由 Summer :: get 返回的 CWiseBinaryOp 对象,删除,最后当 expr 得到求值时, expr 正在引用删除的对象。你可以通过 Holder :: get 返回矩阵的const引用来修复这个问题。


I am writing a library that stores Eigen expression templates as member variables to do the complicated calculations it needs to do. However, it seems like I'm not able to store or return these expression templates unless they are directly converted in MatrixXd or alike. This forces every step to be saved to a temporary, and ruins the efficiency of the whole design.

Here's a short example that causes the trouble. Holder just holds an Eigen matrix, and Summer takes two holders and outputs the sum of the two matrices they hold when you call get(). The test that follows fails (segfault or std::bad_alloc) when the sum expression template is evaluated into a matrix.

Include file

#ifndef PB_SIMPLE_H
#define PB_SIMPLE_H

#include <Eigen/Dense>

template <class EigenType>
class Holder {
   public:
    typedef EigenType result_type;

   private:
    result_type in_;

   public:
    Holder(const EigenType& in) : in_(in) {}
    result_type get() const { return in_; }
};

template <class HoldLeft, class HoldRight>
class Summer {
   public:
    typedef const typename Eigen::CwiseBinaryOp<
        Eigen::internal::scalar_sum_op<double>,
        const typename HoldLeft::result_type,
        const typename HoldRight::result_type> result_type;
    // typedef Eigen::MatrixXd result_type;
   private:
    HoldLeft left_;
    HoldRight right_;

   public:
    Summer(const HoldLeft& left, const HoldRight& right)
        : left_(left), right_(right) {}

    result_type get() const { return left_.get() + right_.get(); }
};

typedef Holder<Eigen::MatrixXd> MatrixHolder;
typedef Summer<MatrixHolder, MatrixHolder> MatrixSummer;

#endif /* PB_SIMPLE_H */

simple test

#include "PbSimple.h"

#include <Eigen/Dense>

int main(int, char * []) {
  const unsigned int szx=10,szy=3;
  Eigen::MatrixXd x(Eigen::MatrixXd::Constant(szx,szy,1));
  MatrixHolder vx(x);
  Eigen::MatrixXd y(Eigen::MatrixXd::Constant(szx,szy,2));
  MatrixHolder vy(y);
  MatrixSummer vsum(vx,vy);
  auto expr = vsum.get();
  MatrixHolder vz(expr); //force evaluation of sum into new matrix, fails here
  return 0;
}

  • In the include file, if you use the commented out typedef instead, it works fine.
  • I suspect the problem is due to a dangling reference, but can't prove it.

解决方案

This is because Holder::get returns a copy of the matrix as a temporary. Then this temporary is stored as a const reference by the CWiseBinaryOp object returned by Summer::get, then this temporary is deleted, and finally when expr gets evaluated, expr is referencing deleted objects. You can fix this issue by making Holder::get returns a const reference to the matrix.

这篇关于从Eigen :: CwiseBinaryOp转换到MatrixXd导致segfault的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆