Question

I don't understand why this code compiles and run without error :

#include <iostream>
#include <stdio.h>
#include <Eigen/Dense>

int
main (int argc, char *argv[])
{
  typedef Eigen::Matrix<double, 5, 3/*FIXME: Should be 5*/> Matrix5;

  Matrix5 test;
  test << 2,0,0,1,1, 
          0,2,0,1,1,
          0,0,2,2,2,
          0,1,2,0,0,
          0,1,1,0,0; // We filled a 5*5 matrix in a 5*3 matrix

  //std::cout << "Test matrix:\n" << test << std::endl;
  return (0);
}

This is how I compiled the code:

g++ test_eigen.cpp -o test_eigen -I/usr/include/eigen3 -O3 -DEIGEN_NO_DEBUG

Uncomment the std::cout, compile, run again and you will get a segmentation fault. I'm using Eigen 3.2.0-8 on Ubuntu 14.04.

As suggested; here is the output of Valgrind (with std::cout commented) :

$ valgrind ./test_eigen
==12380== Memcheck, a memory error detector
==12380== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==12380== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==12380== Command: ./test_eigen
==12380== 
==12380== 
==12380== HEAP SUMMARY:
==12380==     in use at exit: 0 bytes in 0 blocks
==12380==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==12380== 
==12380== All heap blocks were freed -- no leaks are possible
==12380== 
==12380== For counts of detected and suppressed errors, rerun with: -v
==12380== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Was it helpful?

Solution 2

I suspect you compiled with assertions disabled.

Eigen overloads operator<< to enable matrices to be initialized with a comma separated list. (Note that this also means there's an override of the comma operator lurking behind the scenes). That comma separated list of items can contain numbers, but it can also contain a vector or another matrix.

This flexibility comes at a cost. Eigen cannot tell at compile time that the comma separated list contains too many or too few items. It instead detects too many / too few items at run time and complains via an eigen_assert. If you have compiled with assertions disabled, you have let that overly-full list of items change from a SIGABRT into undefined behavior.

This kind of thing happens all the time with undefined behavior, that adding a statement magically lets the code run without error. Don't take this as a sign that things are OK. It just happened to run. Undefined behavior is always bad. Just because it "works" in some cases doesn't mean that your code won't reformat your hard drive the next time you use the program.

OTHER TIPS

Writing past the allocated bounds of a data structure (e.g. writing a 5x5 matrix into an allocated 5x3) is undefined behavior. It may or may not crash, and unfortunately may even run to completion without visible errors.

Run your code with valgrind to pinpoint memory problems similar to the one you described.

Why does this code compile?

Because the compiler will not be able to know how many elements you passed to operator<< at compile time. That information is only available at runtime.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top