我不明白为什么这段代码会编译并运行而不会出错:
#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);
}
这是我编译代码的方式:
g++ test_eigen.cpp -o test_eigen -I/usr/include/eigen3 -O3 -DEIGEN_NO_DEBUG
取消注释std::cout
,编译,再次运行,您将收到分段错误。
我在Ubuntu 14.04上使用Eigen 3.2.0-8。
如建议的那样;这是Valgrind的输出(std::cout
注释):
$ 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)
答案 0 :(得分:5)
写过数据结构的已分配边界(例如,将5x5矩阵写入分配的5x3)是未定义的行为。它可能会也可能不会崩溃,不幸的是,甚至可能会在没有明显错误的情况下运行完毕。
使用valgrind运行代码,以查明与您描述的内容类似的内存问题。
答案 1 :(得分:3)
我怀疑你编译时禁用了断言。
Eigen重载operator<<
以使用逗号分隔列表初始化矩阵。 (请注意,这也意味着在幕后隐藏逗号运算符)。该逗号分隔的项目列表可以包含数字,但它也可以包含一个向量或另一个矩阵。
这种灵活性需要付出代价。 Eigen在编译时无法判断逗号分隔列表包含太多或太少的项目。它反而在运行时检测到太多/太少的项目并通过eigen_assert
进行投诉。如果编译时禁用了断言,则可以让过度完整的项目列表从SIGABRT变为未定义的行为。
这种事情一直都是以未定义的行为发生的,添加一个语句会让代码无错误地运行。不要将此视为事情没问题的标志。它碰巧跑了。未定义的行为总是很糟糕。仅仅因为它&#34;工作&#34;在某些情况下,并不意味着您的代码在下次使用该程序时不会重新格式化您的硬盘。
答案 2 :(得分:1)
为什么这段代码会编译?
因为编译器无法知道在编译时传递给operator<<
的元素数量。该信息仅在运行时可用。