共享指针在循环中超出范围时出错(堆损坏?)
Error when a shared pointer goes out of scope in a loop (Heap corruption?)
逐行调试代码也没有找到问题
我设法从代码库中提取了一个最小示例,它全部归结为以下几行。代码的作用是从对象中读取 3D 点云,将其包装到共享指针中,然后使用 QT 的信号引擎将其发送出去。中间的两行导致错误:
for(vector<Package>::iterator resit = results.begin(); resit != results.end(); resit++) {
// [..] Code ommitted
pcl::PointCloud<pcl::PointXYZ> c = queryObject.getCloud();
// The Ptr typedef resolves to boost::shared_ptr<PointCloud<PointT>>
// (1) Does not work:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(&c);
// (2) Works:
//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(new pcl::PointCloud<pcl::PointXYZ>);
emit this->cluster_added(cloud_ptr);
}
// The error always happens AFTER the FIRST iteration
当我在 (2) 中注释时代码有效(当然注释掉 (1)..)。在这两个版本中,cloud_ptr
是一个共享指针携带云 - 除了第一次是填充云而在第二个版本中不是。
编辑: 既然你们指出了这一点 - 我知道当前版本有多混乱。这是毫无意义的尝试的结果。最初 getCloud()
方法返回一个指向云的指针。但是那个版本也不起作用。这是代码的原始版本:
for(vector<Package>::iterator resit = results.begin(); resit != results.end(); resit++) {
// [..] Code ommitted
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(queryObject.getCloud());
emit this->cluster_added(cloud_ptr);
}
编辑 #2:解决方案
原来我对boost指针有很大的误解。这里正确的做法是创建指针连同点云,然后把东西传给对象:
// Object creation
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
// Do some loading..
[..]
// Use the cloud in the for loop
emit this->cluster_added(queryObject.getCloud());
您的问题是在此处创建堆栈分配变量:
pcl::PointCloud<pcl::PointXYZ> c = queryObject.getCloud();
这个变量在超出范围时会被销毁,所以将它包装成一个 std::shared_ptr
没有意义。
您如何解决问题取决于您的 PointCloud
class 关于复制的语义,但我猜想使用此行可以解决问题:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(new pcl::PointCloud<pcl::PointXYZ>(c));
或者,如果您不希望该指针类型发生变化:
auto cloud_ptr = {make_shared<pcl::PointCloud<pcl::PointXYZ>>(c)};
逐行调试代码也没有找到问题
我设法从代码库中提取了一个最小示例,它全部归结为以下几行。代码的作用是从对象中读取 3D 点云,将其包装到共享指针中,然后使用 QT 的信号引擎将其发送出去。中间的两行导致错误:
for(vector<Package>::iterator resit = results.begin(); resit != results.end(); resit++) {
// [..] Code ommitted
pcl::PointCloud<pcl::PointXYZ> c = queryObject.getCloud();
// The Ptr typedef resolves to boost::shared_ptr<PointCloud<PointT>>
// (1) Does not work:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(&c);
// (2) Works:
//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(new pcl::PointCloud<pcl::PointXYZ>);
emit this->cluster_added(cloud_ptr);
}
// The error always happens AFTER the FIRST iteration
当我在 (2) 中注释时代码有效(当然注释掉 (1)..)。在这两个版本中,cloud_ptr
是一个共享指针携带云 - 除了第一次是填充云而在第二个版本中不是。
编辑: 既然你们指出了这一点 - 我知道当前版本有多混乱。这是毫无意义的尝试的结果。最初 getCloud()
方法返回一个指向云的指针。但是那个版本也不起作用。这是代码的原始版本:
for(vector<Package>::iterator resit = results.begin(); resit != results.end(); resit++) {
// [..] Code ommitted
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(queryObject.getCloud());
emit this->cluster_added(cloud_ptr);
}
编辑 #2:解决方案
原来我对boost指针有很大的误解。这里正确的做法是创建指针连同点云,然后把东西传给对象:
// Object creation
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
// Do some loading..
[..]
// Use the cloud in the for loop
emit this->cluster_added(queryObject.getCloud());
您的问题是在此处创建堆栈分配变量:
pcl::PointCloud<pcl::PointXYZ> c = queryObject.getCloud();
这个变量在超出范围时会被销毁,所以将它包装成一个 std::shared_ptr
没有意义。
您如何解决问题取决于您的 PointCloud
class 关于复制的语义,但我猜想使用此行可以解决问题:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr(new pcl::PointCloud<pcl::PointXYZ>(c));
或者,如果您不希望该指针类型发生变化:
auto cloud_ptr = {make_shared<pcl::PointCloud<pcl::PointXYZ>>(c)};