You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行rosrun时出现munmap_chunk()无效指针错误,未使用malloc/free

解决munmap_chunk(): invalid pointer错误的分析与修复

问题背景

运行ROS节点时触发munmap_chunk(): invalid pointer错误,节点功能为接收点云与costmap数据,检测洞穴后修改costmap实现move_base避障。已使用智能指针、添加mutex同步,但问题仍存在。

错误根源分析

从代码中排查出以下核心问题,直接导致内存损坏:

  • 未定义的函数返回行为:Hole_fn函数声明返回nav_msgs::OccupancyGrid,但当input_cloud_p.size() <= 0时无返回语句,破坏栈结构引发指针错误。
  • 错误的坐标转换逻辑:直接将点云世界坐标强转为costmap栅格坐标,未使用costmap_2d::Costmap2D::worldToMap()做正确转换,导致索引越界、非法访问内存。
  • 全局tf_costmap频繁赋值风险:全局costmap_2d::Costmap2D对象在循环中被频繁赋值,其内部内存管理逻辑可能因重复赋值导致指针混乱。
  • 大对象无意义值传递:cambia函数的costmap_data采用值传递,每次调用拷贝整个大对象,既浪费资源又易引发拷贝/销毁过程中的内存错误。
  • 局部tf::TransformListener生命周期问题:cambia函数内每次创建局部监听器,其生命周期与ROS节点上下文不匹配,引发潜在内存或通信问题。

修复方案与代码修改

1. 修复Hole_fn的返回值问题

确保函数所有分支都有返回值:

nav_msgs::OccupancyGrid Hole_fn(pcl::PointCloud<pcl::PointXYZ>& input_cloud_p,
                                nav_msgs::OccupancyGrid& costmap_data_p,
                                pcl::PointCloud<pcl::PointXYZ>& nube_filt_p)
{
    ros::spinOnce();
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out_ptr(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    sor.setInputCloud(input_cloud_p.makeShared());
    sor.setLeafSize(0.1, 0.1, 0.1);
    sor.filter(*cloud_out_ptr);

    if(input_cloud_p.size() > 0) {
        return cambia(*cloud_out_ptr, costmap_data_p, nube_filt_p);
    }
    // 所有路径返回有效值,这里返回原costmap
    return costmap_data_p;
}

2. 修正坐标转换逻辑

使用worldToMap()完成世界坐标到栅格坐标的转换,避免索引越界:

// 替换cambia函数循环内的坐标处理逻辑
double world_x = point.x;
double world_y = point.y;
int grid_x, grid_y;
if(tf_costmap.worldToMap(world_x, world_y, grid_x, grid_y)) {
    // 坐标转换有效时才执行修改
    std::lock_guard<std::mutex> lock(mtx);
    tf_costmap.setCost(grid_x, grid_y, costmap_2d::LETHAL_OBSTACLE);
}

3. 避免全局tf_costmap频繁赋值

将tf_costmap改为智能指针管理,避免全局对象的赋值风险:

// 修改convertirACostmap2D函数返回智能指针
std::shared_ptr<costmap_2d::Costmap2D> convertirACostmap2D(nav_msgs::OccupancyGrid& occupancy_grid) {
    auto costmap_data = std::make_shared<costmap_2d::Costmap2D>(
        occupancy_grid.info.width, occupancy_grid.info.height,
        occupancy_grid.info.resolution,
        occupancy_grid.info.origin.position.x,
        occupancy_grid.info.origin.position.y
    );

    for(unsigned int x = 0; x < occupancy_grid.info.width; ++x) {
        for(unsigned int y = 0; y < occupancy_grid.info.height; ++y) {
            int8_t occupancy_value = occupancy_grid.data[x + y * occupancy_grid.info.width];
            unsigned char cost = costmap_2d::FREE_SPACE;
            if (occupancy_value == 100) {
                cost = costmap_2d::LETHAL_OBSTACLE;
            } else if (occupancy_value > 0) {
                cost = costmap_2d::INSCRIBED_INFLATED_OBSTACLE;
            }
            costmap_data->setCost(x, y, cost);
        }
    }
    return costmap_data;
}

4. 修改参数传递方式为引用

将cambia函数的costmap_data改为引用传递,避免大对象拷贝:

nav_msgs::OccupancyGrid cambia(pcl::PointCloud<pcl::PointXYZ>& input_cloud,
                               nav_msgs::OccupancyGrid& costmap_data,
                               pcl::PointCloud<pcl::PointXYZ>& nube_filter) {
    // 函数逻辑保持不变,仅修改参数类型
}

5. 全局初始化tf::TransformListener

在全局作用域初始化监听器,确保生命周期与节点一致:

// 全局变量定义
std::mutex mtx;
tf::TransformListener tf_listener; // 全局初始化,避免局部创建的生命周期问题

额外建议

  • 启用编译器警告选项(如-Wall -Wextra),提前发现未定义返回值、类型转换等问题。
  • 使用valgrind工具检测内存问题:valgrind --leak-check=full rosrun your_package your_node

内容的提问来源于stack exchange,提问作者Diego

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:07:01