从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;
}
输出(使用特征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
本身)。
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;
我只是在详细阐述@GuillaumeRacicot的评论,他已经在评论中给出了答案。
CCD_ 8将指向连续存储在存储器中的矩阵CCD_ 9中的数据的指针作为输入。复制m
时,也会复制此指针。
现在,矩阵a
仅在doIt()
的范围内定义,并且在堆栈上分配。一旦doIt()
完成,a
就会被销毁,并且指向它的任何指针都将变为无效。
这正是这里发生的事情:当o
试图访问数据时,它已经不见了,同时内存中的区域可能会被用来做一些不同的事情。这就是为什么你看到一些元素仍然是一样的,但其他元素已经改变了。
我认为此举将有助于
#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;
}
无法测试它,因为我没有本地特征