GDB调试技巧-打印vector的元素值

GDB调试技巧-打印vector的元素值

我们平常在使用GDB调试程序的时候,往往需要查看一个STL容器里面存储的元素的值是多少。但是用GDB的p命令打印容器,我们会得到一堆乱七八糟的东。比如有一个vector<int> nums = {1,2,3},当我们使用p nums命令时,我们得到的结果是:

(gdb) p nums
$1 = {<std::_Vector_base<int, std::allocator<int> >> = {_M_impl = {<std::allocator<int>> = {<__gnu_cxx::new_allocator<int>> = {<No data fields>}, <No data fields>}, 
      _M_start = 0x607080, _M_finish = 0x607084, _M_end_of_storage = 0x607084}}, <No data fields>}

这都是什么鬼!显然,这个结果根本不是我们想要的。那么,怎么让gdb打印出容器实际存储的元素值呢?stack overflow上有很多办法可以实现STL容器的打印,但是都比较麻烦。在这种介绍一种较为简单的方式。

首先来了解一个gdb调试指令,gdb提供了一个call指令, 可以在调试过程中调用任意一个函数,并且可以给函数传入不同的参数。举个例子:

#include<iostream>
using namespace std;
int add(int a, int b);
int main()
{
    cout << add(1, 2);
    return 0;
}

启动gdb开始调试程序,我们就可以使用call 指令来调用add函数了。

[root@localhost ~]# gdb a.out  -q
Reading symbols from /root/a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x4010a3: file main.cpp, line 13.
Starting program: /root/a.out 

Temporary breakpoint 1, main () at main.cpp:13
13      cout << add(1, 2);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-28.el7_5.1.x86_64
(gdb) call add(3, 5)
$1 = 8
(gdb) call add(1000, 2000)
$2 = 3000
(gdb)

可以看到,我们在调试的过程中,可以随意的调用函数。那么有了call指令,打印容器的元素值就很简单了,我们写一个打印函数,在需要查看的时候调用一下不就行了?已vector为例,来看一个小demo程序。

#include<iostream>
#include<vector>
using namespace std;
void pv(vector<int>& nums);
void pv(vector<int>& nums, size_t index);
int main()
{
    vector<int> nums(1,3);
    for (size_t i = 0; i < 20; i++) {
        nums.push_back(i);
    }
    return 0;
}

void pv(vector<int>& nums)
{
    cout << "std::vector of length " << nums.size() << ", capacity " << nums.capacity() << " = {";
    for (size_t i = 0; i < nums.size(); i++) {
        cout << nums[i];
        if (i + 1 < nums.size()) {
            cout << ",";
        }
    }
    cout << "}" << endl;
}

void pv(vector<int>& nums, size_t index) 
{
    if (index >= nums.size()) {
        cout << "index should be in [0, " << nums.size() << ")" << endl;
        return ;
    }
    cout << nums[index] << endl;
}

在代码中,我们定义了两个重载函数pv(print vector),在需要查看vector的元素值的时候,我们就可以调用这两个函数来查看。

[root@localhost ~]# gdb a.out  -q
Reading symbols from /root/a.out...done.
(gdb) start 
Temporary breakpoint 1 at 0x400cef: file main.cpp, line 8.
Starting program: /root/a.out 

Temporary breakpoint 1, main () at main.cpp:8
8    vector<int> nums(1,3);
...
(gdb) call pv(nums)
std::vector of length 14, capacity 16 = {3,0,1,2,3,4,5,6,7,8,9,10,11,12}
(gdb) call pv(nums, 2)
1
(gdb) call pv(nums, 100)
index should be in [0, 14)
(gdb)

可以看到,我们使用call调用pv函数,可以打印出我们想要的结果。其他的容器,如list或者map等,我们只需要定制一个打印函数,在调试的时候使用call调用即可。

全部评论

相关推荐

bg双非本科,方向是嵌入式。这次秋招一共拿到了&nbsp;8&nbsp;个&nbsp;offer,最高年包&nbsp;40w,中间也有一段在海康的实习经历,还有几次国家级竞赛。写这篇不是想证明什么,只是想把自己走过的这条路,尽量讲清楚一点,给同样背景的人一个参考。一、我一开始也很迷茫刚决定走嵌入式的时候,其实并没有一个特别清晰的规划。网上的信息很零散,有人说一定要懂底层,有人说项目更重要,也有人建议直接转方向。很多时候都是在怀疑:1.自己这种背景到底有没有机会2.现在学的东西到底有没有用3.是不是已经开始晚了这些问题,我当时一个都没答案。二、现在回头看,我主要做对了这几件事第一,方向尽早确定,但不把自己锁死。我比较早就确定了嵌入式这个大方向,但具体做哪一块,是在项目、竞赛和实习中慢慢调整的,而不是一开始就给自己下结论。第二,用项目和竞赛去“证明能力”,而不是堆技术名词。我不会刻意追求学得多全面,而是确保自己参与的每个项目,都能讲清楚:我负责了什么、遇到了什么问题、最后是怎么解决的。第三,尽早接触真实的工程环境。在海康实习的那段时间,对我触动挺大的。我开始意识到,企业更看重的是代码结构、逻辑清晰度,以及你能不能把事情说清楚,而不只是会不会某个知识点。第四,把秋招当成一个需要长期迭代的过程。简历不是一次写完的,面试表现也不是一次就到位的。我会在每次面试后复盘哪些问题没答好,再针对性补。三、我踩过的一些坑现在看也挺典型的:1.一开始在底层细节上纠结太久,投入产出比不高2.做过项目,但前期不会总结,导致面试表达吃亏3.早期有点害怕面试,准备不充分就去投这些弯路走过之后,才慢慢找到节奏。四、给和我背景相似的人一点建议如果你也是双非,准备走嵌入式,我觉得有几件事挺重要的:1.不用等“准备得差不多了”再投2.项目一定要能讲清楚,而不是做完就算3.不要只盯着技术,多关注表达和逻辑很多时候,差的不是能力,而是呈现方式。五、写在最后这篇总结不是标准答案,只是我个人的一次复盘。后面我会陆续把自己在嵌入式学习、竞赛、实习和秋招中的一些真实经验拆开来讲,希望能对后来的人有点帮助。如果你正好也在这条路上,希望你能少走一点弯路。
x_y_z1:蹲个后续
点赞 评论 收藏
分享
2025-11-28 16:13
门头沟学院 Java
程序员小白条:年底了,都差不多了
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务