ROS2 Foxy创建节点时valgrind报内存泄漏的原因排查
ROS2 Foxy集成程序valgrind检测GraphListener相关内存泄漏问题说明
- 集成ROS2 Foxy版本节点的可执行程序直接运行功能正常,无报错
- 用指定valgrind命令启动程序时,最初触发rcl init options终结失败错误,排查确认根因是
shutdown()方法调用时机错误 - 修复初始错误后,valgrind检测到总计144字节的明确内存泄漏:56字节为直接泄漏、88字节为间接泄漏
- 已注释
ROS2CommunicationNode内所有自定义代码排除自身逻辑问题,泄漏仍然存在,调用栈显示内存分配来自节点创建流程中rclcpp::graph_listener::GraphListener的初始化逻辑
相关排查信息
valgrind运行命令
timeout --preserve-status 20s valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=../Docs/reports/dynamic_checker/report_valgrind.txt ./bin/Linux/my_app
初始报错内容
[ERROR] [1656072705.908080979] [rclcpp]: failed to finalize rcl init options: init_options->impl argument is null, at /tmp/binarydeb/ros-foxy-rcl-1.1.13/src/rcl/init_options.c:133
初始错误修复代码
if (rclcpp::ok()) { rclcpp::shutdown(); } ros_node_ptr.reset();
泄漏调用栈链路
内存分配的调用链路依次为:malloc → librcl.so内存分配 → rclcpp::Context::get_interrupt_guard_condition → rclcpp::graph_listener::GraphListener构造函数 → rclcpp::node_interfaces::NodeGraph构造函数 → rclcpp::Node构造函数,最终追溯到主函数中make_shared创建ROS2CommunicationNode的流程。
泄漏触发原因
该泄漏是ROS2 Foxy版本rclcpp层的固有已知问题,和自定义业务代码无关:
- 全局Context持有的GraphListener单例采用懒加载逻辑,在第一个节点创建时才会完成初始化,该实例关联的中断守护条件内存,会在程序退出阶段的全局静态对象析构流程中统一回收
- valgrind默认的内存泄漏检测统计时机早于全局静态对象的析构执行节点,因此会把这部分尚未被回收的单例内存判定为明确泄漏
- 该部分内存为单例级一次性分配,程序整个生命周期仅分配一次,不会随节点的创建、销毁操作持续增长,不存在运行时内存持续泄漏的风险,不影响程序正常功能
- 调整
rclcpp::shutdown()和节点指针重置的先后顺序无法消除该泄漏,因为泄漏内存归属全局Context管理,不属于单个节点实例的生命周期管辖范围
内容的提问来源于stack exchange,提问作者Simone Morettini
相关产品推荐
相关产品推荐

