New user self-registration is disabled due to spam. Please email eigen-core-team @ if you need an account.
Before reporting a bug, please make sure that your Eigen version is up-to-date!
Bug 1706 - SparseMatrix reallocation throws std::bad_alloc when StorageIndex > Eigen::Index
Summary: SparseMatrix reallocation throws std::bad_alloc when StorageIndex > Eigen::Index
Alias: None
Product: Eigen
Classification: Unclassified
Component: Sparse (show other bugs)
Version: 3.3 (current stable)
Hardware: All All
: Normal Internal Design
Assignee: Nobody
Depends on:
Blocks: 3.x
  Show dependency treegraph
Reported: 2019-05-06 13:30 UTC by Robin Deits
Modified: 2019-07-16 13:02 UTC (History)
3 users (show)


Description Robin Deits 2019-05-06 13:30:51 UTC
It appears that the internal resize methods for SparseMatrix spuriously throw std::bad_alloc when using a SparseMatrix whose StorageIndex is of a wider integer type than Eigen::Index. 

For example, consider the following snippet, in which we construct a SparseMatrix using 64-bit StorageIndex in a context where Eigen::Index is a 32-bit integer: 

#include <Eigen/Core>
#include <Eigen/Sparse>

int main() {
	Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t> mat(5, 5);
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			mat.coeffRef(i, j) = 1;
	return 0;

Compiling this with: 

g++ main.cpp -o main -Ieigen-3.3.7 -std=c++11

(assuming the Eigen sources live in `./eigen-3.3.7`) and running it with `./main` will abort with: 

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
Aborted (core dumped)

The issue appears to stem from the following line in `SparseCore/CompressedStorage.h`:

Index realloc_size = (std::min<Index>)(NumTraits<StorageIndex>::highest(),  size + Index(reserveSizeFactor*double(size)));

when `StorageIndex` is wider than `Index`, this results in `realloc_size` being set to -1, which triggers the `internal::throw_std_bad_alloc()` on the next line.
Comment 1 Christoph Hertzberg 2019-05-06 14:05:24 UTC
This looks like an uncovered border case indeed. 
We could replace all `Index` by `size_t` or `ptrdiff_t` in the line you found. And additionally make sure (at compile-time) that StorageIndex is not larger that size_t, of course.
Comment 2 Christoph Hertzberg 2019-07-16 13:02:48 UTC
I'm actually tending to just disallow
  sizeof(StorageIndex) > sizeof(DenseIndex)

Using StorageIndex = int64_t is barely useful on 32bit systems, and setting DenseIndex to int32_t is barely useful on 64bit systems.

Note You need to log in before you can comment on or make changes to this bug.