HyperBoar
HyperBoar

Reputation: 113

workaround for Eigen::Matrix to release data

I want to use Eigen3 on data coming from another library. An earlier answer by ggael indicates a way for Eigen::Matrix to adopt preexsisting data with the new keyword. However, this is not sufficient for me, because the resulting Matrix still seems to acquire ownership of the data, meaning that it will free the data when going out of scope. To wit, this is a crasher if data eventually gets deleted by the library it comes from:

void crasher(double* data, size_t dim)
{
  MatrixXd m;

  new (&m) Map<MatrixXd>(data,dim,dim); // matrix adopts the passed data
  m.setRandom(); cout<<m<<endl; // manipulation of the passed data via the Matrix interface
} // data deleted by m => potential problem in scope of function call

I have come up with two workarounds:

void nonCrasher1(double* data, size_t dim)
{
  MatrixXd m; // semantically, a non-owning matrix
  const Map<const MatrixXd> cache(m.data(),0,0); // cache the original „data” (in a const-correct way)

  new (&m) Map<MatrixXd>(data,dim,dim); // matrix adopts the passed data
  m.setRandom(); cout<<m<<endl; // manipulation of the passed data via the Matrix interface

  new (&m) Map<const MatrixXd>(cache); // re-adopting the original data
} // original data deleted by m

This is rather inconvenient because of the presence of cache. The other is free from this problem:

void nonCrasher2(double* data, size_t dim) // no need for caching
{
  MatrixXd m; // semantically, a non-owning matrix

  new (&m) Map<MatrixXd>(data,dim,dim); // matrix adopts the passed data
  m.setRandom(); cout<<m<<endl; // manipulation of the passed data via the Matrix interface

  new (&m) Map<MatrixXd>(nullptr,0,0); // adopting nullptr for subsequent deletion
} // nullptr „deleted” by m (what happens with original data [if any]?)

However, here it’s unclear what happens with the original data of m (if any – all this is not completely clear from the documentation of Eigen3).

My question is whether there is a canonical way for Eigen::Matrix to release ownership of it’s data (self-allocated or adopted).

Upvotes: 3

Views: 1486

Answers (1)

ggael
ggael

Reputation: 29225

In nonCrasher2 nothing happen to data, except that it has been filled with random values on purpose.

However, this still look like hackish, and the clean approach be to use a Map object instead of MatrixXd:

Map<MatrixXd> m(data, dim, dim);
m.setRandom();

If you need m to be a MatrixXd because you need to call functions taking MatrixXd objects, and such functions cannot be templated, then you might consider generalizing these functions to take Ref<MatrixXd> objects. By default, a Ref<MatrixXd> can accept any expression which storage reassemble to a MatrixXd with arbitrary leading dimension. It has been introduced in Eigen 3.2, check the doc for more details.

Upvotes: 1

Related Questions