在学习PCL官方文档Filtering一节中,或者学习《点云库PCL从入门到精通》的第六章第6.2.1节使用直通滤波器对点云进行滤波处理时,会有如下代码报错。
#include
#include
#include
#include
int
main (int argc, char** argv)
{ srand(time(0));
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
//填入点云数据
cloud->width = 5;
cloud->height = 1;
cloud->points.resize (cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size (); ++i)
{
cloud->points[i].x = rand () / (RAND_MAX + 1.0f)-0.5;
cloud->points[i].y = rand () / (RAND_MAX + 1.0f)-0.5;
cloud->points[i].z = rand () / (RAND_MAX + 1.0f)-0.5;
}
std::cerr << "Cloud before filtering: " << std::endl;
for (size_t i = 0; i < cloud->points.size (); ++i)
std::cerr << " " << cloud->points[i].x << " "
<< cloud->points[i].y << " "
<< cloud->points[i].z << std::endl;
// 创建滤波器对象
pcl::PassThrough pass;
pass.setInputCloud (cloud);
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
//pass.setFilterLimitsNegative (true);
pass.filter (*cloud_filtered);
std::cerr << "Cloud after filtering: " << std::endl;
for (size_t i = 0; i < cloud_filtered->points.size (); ++i)
std::cerr << " " << cloud_filtered->points[i].x << " "
<< cloud_filtered->points[i].y << " "
<< cloud_filtered->points[i].z << std::endl;
return (0);
}
运行错误为:
定位一下free看看
问题描述:free(ptr)出错。free,没看懂,但是ptr是
pcl::PointCloud::Ptr cloud_filtered(new pcl::PointCloud);
中的Ptr,按住ctrl,追踪Ptr
追踪这个shared_ptr
找了这个类的析构函数:
析构函数调用_Decref():追踪这个函数。找到一个Destory()。差不多找到了。
追踪这个_Destory
还是看不懂了。
但是至此我们大概猜到:是我们对只能共享指针Ptr使用不对。
我们上网搜索:还真找到了。
对方在stackOverflow上的代码如下:
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv) {
pcl::PointCloud cloud;
// Fill in the cloud data
cloud.width = 10000;
cloud.height = 1;
cloud.is_dense = false;
cloud.points.resize(cloud.width * cloud.height);
for (size_t i = 0; i < cloud.points.size(); ++i) {
cloud.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].r = 256 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].g = 256 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].b = 256 * rand() / (RAND_MAX + 1.0f);
}
//pcl::io::savePCDFileASCII("testpcd.pcd", cloud);
pcl::PointCloud::Ptr cloud_ptr(&cloud);
//visualiser
boost::shared_ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0);
viewer->addPointCloud(cloud_ptr, "sample cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
viewer->addCoordinateSystem(1.0);
viewer->initCameraParameters();
//viewer->resetCameraViewpoint("sample cloud");
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
运行错误如下:与我们的略有不同。
先看解决方案:
原文:
You are taking a pointer to an object on the stack, and handing it to a shared pointer.
At the end of the scope, the shared pointer destructor then attempts to free up that memory (which it cannot do since it is on the stack, not the heap).
Try something like this instead:
试着翻译一下:
将指向栈上对象的指针传递给共享指针。在作用域的末尾,共享指针析构函数然后尝试释放该内存(它不能这样做,因为它是在栈上,而不是在堆上)。试着这样做:
我们按照这个方法修改试试。
//pcl::PointCloud cloud;
pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
将cloud变量生命在了堆中。Ptr是一个共享指针,所以调用其属性,需要用->。代码修改如下。
#include
#include
#include
#include
using namespace std;
int main(int argc, char** argv) {
//pcl::PointCloud cloud;
pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
// Fill in the cloud data
cloud->width = 10000;
cloud->height = 1;
cloud->is_dense = false;
cloud->points.resize(cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size(); ++i) {
cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f); // 属性调用由.变->
cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f); // 属性调用由.变->
cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
cloud->points[i].r = 256 * rand() / (RAND_MAX + 1.0f);
cloud->points[i].g = 256 * rand() / (RAND_MAX + 1.0f);
cloud->points[i].b = 256 * rand() / (RAND_MAX + 1.0f);
}
//pcl::io::savePCDFileASCII("testpcd.pcd", cloud);
//pcl::PointCloud::Ptr cloud_ptr(&cloud); // 原来这样,
pcl::PointCloud::Ptr cloud_ptr(cloud); // 这里要修改。
//visualiser
boost::shared_ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0);
viewer->addPointCloud(cloud_ptr, "sample cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
viewer->addCoordinateSystem(1.0);
viewer->initCameraParameters();
//viewer->resetCameraViewpoint("sample cloud");
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
注意:这里这样修改。问题解决了。
//pcl::PointCloud::Ptr cloud_ptr(&cloud); // 原来这样,
pcl::PointCloud::Ptr cloud_ptr(cloud); // 这里要修改。
我把问题凝练了一下,省去多余代码:总结为如下四行代码的问题:
#include
#include
int main(int argc, char** argv) {
// 这两行会报错。 // 因为cloud_ptr开辟在了栈中。
pcl::PointCloud cloud;
pcl::PointCloud::Ptr cloud_ptr(&cloud);
// 改成这两行才可以跑通。 // ptr开辟在堆中。
//pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
//pcl::PointCloud::Ptr cloud_ptr(cloud);
return (0);
}
// 上面两行会报错:02 滤波.exe 已触发了一个断点。
// void _Decref() noexcept { // decrement use count
//if (_MT_DECR(_Uses) == 0) {
// _Destroy(); // 错误定位在这里。
// _Decwref();
//}
// }
// 改正方法:参照这个:
// https://stackoverflow.com/questions/38090862/pcl-visualizer-exception-thrown-from-eigen-when-exit-visualizer-window
// 将Ptr智能指针开辟在堆中。
// 然后把这个指针变量直接丢给新的构造函数。这样就没问题了。新的Ptr开辟在堆中。
我们再回来解决我们自己的问题。
我们可以把我们自己的代码也凝练,但是,我们发现代码中使用的cloud都已经是Ptr类型。而且也都是通过new的方式,开辟在了堆中。
转一圈,还是没解决我们自己的问题。
问题:记录:改日重新攻克。目前的想到是:try然后放弃。或者手动释放。不知道linux系统下如何?