【未解决:问题记录:】PCL中Ptr错误:已触发了一个断点。

本文档详细记录了一位开发者在使用PCL库进行点云滤波时遇到的问题。代码中,使用PassThrough滤波器对点云数据进行处理,由于将栈上的对象指针传递给了智能指针,导致了内存释放错误。解决方案是确保对象在堆上分配,并正确传递给智能指针。问题最终通过修改代码,将对象实例化在堆上并正确赋值给智能指针得到解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在学习PCL官方文档Filtering一节中,或者学习《点云库PCL从入门到精通》的第六章第6.2.1节使用直通滤波器对点云进行滤波处理时,会有如下代码报错。

#include <iostream>
#include <ctime>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>

int
 main (int argc, char** argv)
{ srand(time(0));
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  //填入点云数据
  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<pcl::PointXYZ> 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<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

 中的Ptr,按住ctrl,追踪Ptr

 追踪这个shared_ptr

 找了这个类的析构函数

 析构函数调用_Decref():追踪这个函数。找到一个Destory()。差不多找到了。

 追踪这个_Destory

还是看不懂了。

 但是至此我们大概猜到:是我们对只能共享指针Ptr使用不对。

我们上网搜索:还真找到了

对方在stackOverflow上的代码如下:

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

using namespace std;

int main(int argc, char** argv) {

    pcl::PointCloud<pcl::PointXYZRGB> 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<pcl::PointXYZRGB>::Ptr cloud_ptr(&cloud);

    //visualiser
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));

    viewer->setBackgroundColor(0, 0, 0);
    viewer->addPointCloud<pcl::PointXYZRGB>(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<pcl::PointXYZRGB> cloud;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);

 将cloud变量生命在了堆中。Ptr是一个共享指针,所以调用其属性,需要用->。代码修改如下。

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>

using namespace std;


int main(int argc, char** argv) {

    //pcl::PointCloud<pcl::PointXYZRGB> cloud;
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);

    // 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<pcl::PointXYZRGB>::Ptr cloud_ptr(&cloud);  // 原来这样,
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_ptr(cloud);  // 这里要修改。

    //visualiser
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));

    viewer->setBackgroundColor(0, 0, 0);
    viewer->addPointCloud<pcl::PointXYZRGB>(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<pcl::PointXYZRGB>::Ptr cloud_ptr(&cloud);  // 原来这样,
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_ptr(cloud);  // 这里要修改。

我把问题凝练了一下,省去多余代码:总结为如下四行代码的问题:

 

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>



int main(int argc, char** argv) {

    // 这两行会报错。  // 因为cloud_ptr开辟在了栈中。
    pcl::PointCloud<pcl::PointXYZRGB> cloud;
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_ptr(&cloud);


    // 改成这两行才可以跑通。  // ptr开辟在堆中。
    //pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    //pcl::PointCloud<pcl::PointXYZRGB>::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系统下如何?

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值