приведение из Eigen :: CwiseBinaryOp к MatrixXd вызывает segfault

Я пишу библиотеку, в которой шаблоны Eigen-выражений хранятся как переменные-члены для выполнения сложных вычислений, необходимых для этого. Тем не менее, похоже, что я не могу сохранить или вернуть эти шаблоны выражений, если они не конвертированы напрямую в MatrixXd или тому подобное. Это заставляет каждый шаг быть сохраненным во времени и разрушает эффективность всего проекта.

Вот короткий пример, который вызывает проблемы. Holder просто содержит собственную матрицу, а Summer берет два держателя и выводит сумму двух матриц, которые они хранят при вызове get (). Следующий тест не пройден (segfault или std :: bad_alloc), когда шаблон выражения суммы оценивается в матрицу.

Включить файл

#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 */

простой тест

#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;
}
  • Во включаемом файле, если вместо этого вы используете закомментированный typedef, он работает нормально.
  • Я подозреваю, что проблема из-за свисающей ссылки, но не могу доказать это.

0

Решение

Это потому что Holder::get возвращает копию матрицы как временную. Затем этот временный объект сохраняется как постоянная ссылка CWiseBinaryOp объект, возвращенный Summer::get, то этот временный удаляется, и, наконец, когда expr оценивается, expr ссылается на удаленные объекты. Вы можете решить эту проблему, сделав Holder::get возвращает постоянную ссылку на матрицу.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]