Eigen Instantiation of Dynamic Matrix Encountering OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG During Compilation

Viewed 135

I have a class that uses a dynamic Eigen::Matrix of doubles (i.e. Eigen::MatrixXd ), that has max rows and cols specified at compile time. During use, the dimensions may be less than the maximum. The purpose of specifying the max rows and cols is to avoid dynamic reallocation using the heap if the matrix size increases.

When I compile the code, I get an OBJECT_ALLOCATED_ON_STACK_IS_TOO_BIG error. I'm using Eigen 3.2 and VisualStudio 2017 with the default options and flags. This error occurs whether in Debug or Release mode. The Target arch is x64.

Here's the code (simplified):

class MyClass {
public:
  MyClass();
  ~MyClass();
 
private:
  // Create a member that is an Eigen::Matrix of doubles w/ dynamic sizing and max rows and cols 
  // at compile time = 1024.
  Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, 0, 1024, 1024 > x;

  // Eigen::MatrixXd x(1024, 1024); // -- FAILS too!
};

What appears to be happening is that during the template expansion, the dynamic nature of the array declaration is ignored and the expansion thinks it is a static array which causes the size checking in Eigen::internal::check_static_allocation_size() to assert. I'm not sure why the dynamic flags/constants are being ignored.

Thanks,

--Mike

1 Answers

This is shown in the documentation

ABI and storage layout

The table below summarizes the ABI of some possible Matrix instances which is fixed thorough the lifetime of Eigen 3.

...

Matrix<T,Dynamic,Dynamic,0,MaxRows,MaxCols> 

Equivalent C structure

struct {
  T data[MaxRows*MaxCols];  // with (size_t(data)%A(MaxRows*MaxCols*sizeof(T)))==0
  Eigen::Index rows, cols;
 };

Eg, you're specifying dynamic matrix with a constant size container (for speed probably). But that container is a C-array and thus allocated on the place where you allocate your object. Which is likely on the stack. 1024x1024 elements of a 8-byte double is too large for the stack.

You should just use Matrix<T,Dynamic,Dynamic> for an allocated dynamic matrix.

Edit:

If you want to pre-allocate memory for your dynamic matrix, use the resize member function. You can for example do that in the constructor.

x.resize(1024, 1024);

Edit 2:

I'm not sure if resizing the matrix can ever be done without reallocation. You could look into conservativeResize

Resizes the matrix to rows x cols while leaving old values untouched. The method is intended for matrices of dynamic size. If you only want to change the number of rows and/or of columns, you can use conservativeResize(NoChange_t, Index) or conservativeResize(Index, NoChange_t). Matrices are resized relative to the top-left element. In case values need to be appended to the matrix they will be uninitialized.

Related