从lambda函数返回Eigen :: Map会产生错误的输出:
#include<iostream>
#include<eigen3/Eigen/Dense>
using namespace std;
using namespace Eigen;
int main(){
auto doIt = [](){
MatrixXd a = MatrixXd::Random(2,3);
Map<MatrixXd> m(a.data(),2,3);
cout << "a:\n" << a << endl;
cout << "m:\n" << m << endl;
return m;
};
MatrixXd o(2,3);
o = doIt();
cout << "o:\n" << o << endl;
return 0;
}
输出(使用Eigen 3.2.9-1):
a:
0.680375 0.566198 0.823295
-0.211234 0.59688 -0.604897
m:
0.680375 0.566198 0.823295
-0.211234 0.59688 -0.604897
o:
5.15038e-317 0.566198 0.823295
-0.211234 0.59688 -0.604897
如果使用clang++ -std=c++11 -fsanitize=address
编译,我会进一步获得堆使用后免费错误。 (clang 3.7.1版)
如果我将lambda转换为返回Eigen::MatrixXd
的函数,它可以工作 - 可能是因为额外的复制。有没有办法让它在lambda中工作,而不使用额外的MatrixXd
并将地图内容复制到它?
(在我的用例中,lambda只能访问Map m
而不能访问MatrixXd a
本身。
答案 0 :(得分:2)
Map
不拥有数据,只包装现有数据。如果数据被释放或修改Map
将无法识别。而这正是这里发生的事情:
auto doIt = [](){
// Here MatrixXd dynamically allocates memory for its content
MatrixXd a = MatrixXd::Random(2,3);
// Now you save pointer to this allocated memory
Map<MatrixXd> m(a.data(),2,3);
cout << "a:\n" << a << endl;
cout << "m:\n" << m << endl;
return m;
// When leaving the scope via return or simple end of block
// all local variables will be destroyed.
// When destorying, Matrix will also free
// what it owns thus Map will point to invalid memory
};
所以基本上你正在访问一个释放的内存。您需要返回拥有资源的对象:
auto doIt = [](){
return MatrixXd::Random(2,3);
};
auto a = doIt();
Map<MatrixXd> m(a.data(),2,3);
cout << "a:\n" << a << endl;
cout << "m:\n" << m << endl;
MatrixXd o(2,3);
cout << "o:\n" << o << endl;
答案 1 :(得分:1)
我正在详细阐述@GuillaumeRacicot的评论,他已经在评论中给出了答案。
Map<MatrixXd> m(a.data(),2,3);
将指向矩阵m
中数据的指针作为输入,该数据连续存储在内存中。复制m
时,也会复制此指针。
现在,矩阵a
仅在doIt()
的范围内定义,并在堆栈上分配。完成doIt()
后,a
将被销毁,任何指向它的指针都将无效。
这正是这里发生的事情:当o
试图访问数据时,它已经消失,而内存中的区域可能已经被用于同时不同的东西。这就是为什么你看到一些元素仍然相同,但其他元素已经改变。
答案 2 :(得分:-1)
我认为此举将有所帮助
#include<iostream>
#include<eigen3/Eigen/Dense>
using namespace std;
using namespace Eigen;
int main(){
auto&& doIt = [](){
MatrixXd a = MatrixXd::Random(2,3);
Map<MatrixXd> m(a.data(),2,3);
cout << "a:\n" << a << endl;
cout << "m:\n" << m << endl;
return std::move(m);
};
MatrixXd o(2,3);
o = doIt();
cout << "o:\n" << o << endl;
return 0;
}
无法测试,因为我没有本地本地