使用GDB调试ROS2程序
-
我们使用
backward_ros
功能包来快速实现用GDB
调试ROS2
程序。backward_ros
功能包介绍backward_ros
功能包是对backward-cpp
包的ROS2
封装,以便可以简单快速地使用GDB
工具。backward-cpp
包的介绍可以查看其仓库:https://github.com/bombela/backward-cpp
使用
backward_ros
功能包实现GDB
调试ROS2
程序只需下面三个步骤:- 添加
backward_ros
到package.xml
文件。
<depend>backward_ros</depend>
- 添加
backward_ros
到CMakeLists.txt
文件中。
find_package(backward_ros REQUIRED)
- 使用
Debug
或者RelWithDebInfo
选项编译程序。
colcon build --cmake-args '-DCMAKE_BUILD_TYPE=RelWithDebInfo'
backward_ros
功能包的github
地址(ROS2
程序使用foxy-devel
分支):https://github.com/pal-robotics/backward_ros.git
运行示例程序
获取示例程序:
git clone https://github.com/shoufei403/gdb_test.git
编译时选择
RelWithDebInfo
或Debug
编译类型时可以看到是代码的哪一行出了问题colcon build --cmake-args '-DCMAKE_BUILD_TYPE=RelWithDebInfo'
运行测试程序
source install/setup.bash ros2 run gdb_test gdb_test
可以看到下面的堆栈信息
Stack trace (most recent call last): #4 Object "", at 0xffffffffffffffff, in #3 Source "/home/kevin/gdb_test/src/gdb_test/gdb_test.cpp", line 50, in _start [0x56060876e91d] 47: rclcpp::spin(std::make_shared<MinimalSubscriber>()); 48: rclcpp::shutdown(); 49: return 0; > 50: } #2 Source "../csu/libc-start.c", line 308, in __libc_start_main [0x7f1b2f271082] #1 | Source "/home/kevin/gdb_test/src/gdb_test/gdb_test.cpp", line 47, in make_shared<MinimalSubscriber> | 45: { | 46: rclcpp::init(argc, argv); | > 47: rclcpp::spin(std::make_shared<MinimalSubscriber>()); | 48: rclcpp::shutdown(); | 49: return 0; | Source "/usr/include/c++/9/bits/shared_ptr.h", line 718, in allocate_shared<MinimalSubscriber, std::allocator<MinimalSubscriber> > | 716: typedef typename std::remove_cv<_Tp>::type _Tp_nc; | 717: return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(), | > 718: std::forward<_Args>(__args)...); | 719: } | Source "/usr/include/c++/9/bits/shared_ptr.h", line 702, in shared_ptr<std::allocator<MinimalSubscriber> > | 700: { | 701: return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a}, | > 702: std::forward<_Args>(__args)...); | 703: } | Source "/usr/include/c++/9/bits/shared_ptr.h", line 359, in __shared_ptr<std::allocator<MinimalSubscriber> > | 357: template<typename _Alloc, typename... _Args> | 358: shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args) | > 359: : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...) | 360: { } | Source "/usr/include/c++/9/bits/shared_ptr_base.h", line 1344, in __shared_count<MinimalSubscriber, std::allocator<MinimalSubscriber> > | 1342: template<typename _Alloc, typename... _Args> | 1343: __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args) | >1344: : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...) | 1345: { _M_enable_shared_from_this_with(_M_ptr); } | Source "/usr/include/c++/9/bits/shared_ptr_base.h", line 679, in _Sp_counted_ptr_inplace<> | 677: auto __guard = std::__allocate_guarded(__a2); | 678: _Sp_cp_type* __mem = __guard.get(); | > 679: auto __pi = ::new (__mem) | 680: _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...); | 681: __guard = nullptr; | Source "/usr/include/c++/9/bits/shared_ptr_base.h", line 548, in construct<MinimalSubscriber> | 546: // _GLIBCXX_RESOLVE_LIB_DEFECTS | 547: // 2070. allocate_shared should use allocator_traits<A>::construct | > 548: allocator_traits<_Alloc>::construct(__a, _M_ptr(), | 549: std::forward<_Args>(__args)...); // might throw | 550: } | Source "/usr/include/c++/9/bits/alloc_traits.h", line 483, in construct<MinimalSubscriber> | 481: construct(allocator_type& __a, _Up* __p, _Args&&... __args) | 482: noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) | > 483: { __a.construct(__p, std::forward<_Args>(__args)...); } | 484: | 485: /** Source "/usr/include/c++/9/new", line 174, in main [0x56060876e7b1] 172: // Default placement versions of operator new. 173: _GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT > 174: { return __p; } 175: _GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT 176: { return __p; } #0 Source "/home/kevin/gdb_test/src/gdb_test/gdb_test.cpp", line 33, in MinimalSubscriber [0x56060878c1a8] 30: "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1)); 31: 32: int * p = nullptr; > 33: *p = 1;//制造断错误 34: } 35: 36: private: Segmentation fault (Address not mapped to object [(nil)])
其他使用GDB的方法可以参考此文档
https://navigation.ros.org/tutorials/docs/get_backtrace.html#preliminaries
- 添加
-
@首飞Kevin 赞,这个可以用vscode打短点调试吗,还是说把gdb的bt堆栈在终端打出来的功能
-
@小鱼 段错误时会在命令窗口打印出堆栈信息。
-
@小鱼 没有用vscode的,应该是打不了断点。
-
为啥我的只能打印一半呀,我的ROS2是安装在ARM64的Ubuntu系统中,大佬能解答一下吗,万分感谢!!!