实例

我以自己曾经写的一段实际代码为例,来讲解究竟该怎么进行GDB调试。

实例地址:

GitHub:https://github.com/yngzMiao/protobuf-parser-tool

实例的功能是生成和解析proto文件,分为C++python版本。其中,C++版本采用的是CMakeLists.txt进行编译,按照以下命令可以生成可执行文件:

mkdir build && cd build
cmake ..
make

最终可执行文件example_person是在build文件夹下。

如果不太了解CMakeLists.txt的,可以阅读博文:【CMake】CMakeLists.txt的超傻瓜手把手教程(附实例源码)

前提

一般情况下,GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,必须要把符号表信息加到可执行文件中。使用编译器的-g参数可以做到这一点。比如:

g++ -g hello.cpp -o hello

当然,本实例中,在最顶层的CMakeLists.txt添加以下语句:

add_definitions("-Wall -g")

代码内容

接下来看一下主代码的内容,即example_person.cpp

#include <iostream>
#include "General_buf_read.h"
#include "General_buf_write.h"
#include "Person.pb.h" namespace PersonProto {class Person;
};namespace GeneralBuf {template <typename T>class GeneralProtoWriter;typedef GeneralProtoWriter<PersonProto::Person> PersonProtoWriter;template <typename T>class GeneralProtoReader;typedef GeneralProtoReader<PersonProto::Person> PersonProtoReader;
};int main(int argc, char const *argv[])
{GeneralBuf::PersonProtoWriter writer;std::string filename = "Person_test.proto";int64_t version = 20191001;writer.startWriter(filename, version);PersonProto::Person *person1 = new PersonProto::Person();person1->set_id(100000);person1->set_name("zhangsan");person1->set_age(20);person1->add_email("123456@qq.com");person1->add_email("234567@qq.com");PersonProto::PhoneNumber *phone1 = person1->add_phone();PersonProto::PhoneNumber *phone2 = person1->add_phone();phone1->set_number("987654");phone1->set_type(PersonProto::PhoneType::MOBILE);phone2->set_number("876543");phone2->set_type(PersonProto::PhoneType::HOME);PersonProto::Address *addr = person1->mutable_address();addr->set_country("china");addr->set_detail("beijing");writer.write(person1);writer.stopWriter();GeneralBuf::PersonProtoReader reader;reader.startReader(filename);std::cout << "version : " << reader.getVersion() << "\n";std::cout << "cnt : " << reader.getFrameCount() << "\n";reader.setFrameIndex(0);PersonProto::Person *person = new PersonProto::Person();reader.read(person);person->PrintDebugString();return 0;
}

使用GDB调试

下面使用GDB来对生成的可执行文件进行调试,调试命令如下,解释在后面进行了标注:

yngzmiao@yngzmiao-virtual-machine:~/github/protobuf-parser-tool/c++/build$ gdb example_person  <--------启动GDB
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from example_person...done.
(gdb) l                                                     <---------------list,查看源码
6   namespace PersonProto {
7     class Person;
8   };
9
10  namespace GeneralBuf {
11    template <typename T>
12    class GeneralProtoWriter;
13    typedef GeneralProtoWriter<PersonProto::Person> PersonProtoWriter;
14    template <typename T>
15    class GeneralProtoReader;
(gdb)                                                       <---------------直接回车,重复上一条命令
16    typedef GeneralProtoReader<PersonProto::Person> PersonProtoReader;
17  };
18
19  int main(int argc, char const *argv[])
20  {
21    GeneralBuf::PersonProtoWriter writer;
22    std::string filename = "Person_test.proto";
23    int64_t version = 20191001;
24    writer.startWriter(filename, version);
25
(gdb)                                                        <---------------直接回车,重复上一条命令
26    PersonProto::Person *person1 = new PersonProto::Person();
27    person1->set_id(100000);
28    person1->set_name("zhangsan");
29    person1->set_age(20);
30
31    person1->add_email("123456@qq.com");
32    person1->add_email("234567@qq.com");
33    PersonProto::PhoneNumber *phone1 = person1->add_phone();
34    PersonProto::PhoneNumber *phone2 = person1->add_phone();
35    phone1->set_number("987654");
(gdb)                                                        <---------------直接回车,重复上一条命令
36    phone1->set_type(PersonProto::PhoneType::MOBILE);
37    phone2->set_number("876543");
38    phone2->set_type(PersonProto::PhoneType::HOME);
39
40    PersonProto::Address *addr = person1->mutable_address();
41    addr->set_country("china");
42    addr->set_detail("beijing");
43
44    writer.write(person1);
45    writer.stopWriter();
(gdb)                                                        <---------------直接回车,重复上一条命令
46
47    GeneralBuf::PersonProtoReader reader;
48    reader.startReader(filename);
49
50    std::cout << "version : " << reader.getVersion() << "\n";
51    std::cout << "cnt : " << reader.getFrameCount() << "\n";
52    reader.setFrameIndex(0);
53    PersonProto::Person *person = new PersonProto::Person();
54    reader.read(person);
55    person->PrintDebugString();
(gdb)                                                        <---------------直接回车,重复上一条命令
56
57    return 0;
58  }
(gdb) b 44                                                   <---------------break,设置断点
Breakpoint 1 at 0x40dd2d: file /home/yngzmiao/github/protobuf-parser-tool/c++/example_person.cpp, line 44.
(gdb) b 55                                                   <---------------break,设置断点
Breakpoint 2 at 0x40de34: file /home/yngzmiao/github/protobuf-parser-tool/c++/example_person.cpp, line 55.
(gdb) i b                                                    <---------------info break,查看断点信息
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040dd2d in main(int, char const**) at /home/yngzmiao/github/protobuf-parser-tool/c++/example_person.cpp:44
2       breakpoint     keep y   0x000000000040de34 in main(int, char const**) at /home/yngzmiao/github/protobuf-parser-tool/c++/example_person.cpp:55
(gdb) r                                                      <---------------run,运行程序,在断点处停止
Starting program: /home/yngzmiao/github/protobuf-parser-tool/c++/build/example_person
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".Breakpoint 1, main (argc=1, argv=0x7fffffffdc88) at /home/yngzmiao/github/protobuf-parser-tool/c++/example_person.cpp:44
44    writer.write(person1);
(gdb) p person1                                              <---------------print,打印
$1 = (PersonProto::Person *) 0x6375d0
(gdb) p *person1                                             <---------------print,打印
$2 = {<google::protobuf::Message> = {<No data fields>}, static kIdFieldNumber = 1, static kNameFieldNumber = 2, static kAgeFieldNumber = 3, static kEmailFieldNumber = 4, static kPhoneFieldNumber = 5, static kAddressFieldNumber = 6, _unknown_fields_ = {fields_ = 0x0}, _has_bits_ = {39}, _cached_size_ = 0, name_ = 0x636fd0, id_ = 100000, age_ = 20, email_ = {<google::protobuf::internal::RepeatedPtrFieldBase> = {static kInitialSize = 0, elements_ = 0x636830, current_size_ = 2, allocated_size_ = 2, total_size_ = 4}, <No data fields>}, phone_ = {<google::protobuf::internal::RepeatedPtrFieldBase> = {static kInitialSize = 0, elements_ = 0x634180, current_size_ = 2, allocated_size_ = 2, total_size_ = 4}, <No data fields>}, address_ = 0x631f60, static default_instance_ = 0x6324c0}
(gdb) p *(PersonProto::Person *) 0x6375d0                    <---------------print,打印
$3 = {<google::protobuf::Message> = {<No data fields>}, static kIdFieldNumber = 1, static kNameFieldNumber = 2, static kAgeFieldNumber = 3, static kEmailFieldNumber = 4, static kPhoneFieldNumber = 5, static kAddressFieldNumber = 6, _unknown_fields_ = {fields_ = 0x0}, _has_bits_ = {39}, _cached_size_ = 0, name_ = 0x636fd0, id_ = 100000, age_ = 20, email_ = {<google::protobuf::internal::RepeatedPtrFieldBase> = {static kInitialSize = 0, elements_ = 0x636830, current_size_ = 2, allocated_size_ = 2, total_size_ = 4}, <No data fields>}, phone_ = {<google::protobuf::internal::RepeatedPtrFieldBase> = {static kInitialSize = 0, elements_ = 0x634180, current_size_ = 2, allocated_size_ = 2, total_size_ = 4}, <No data fields>}, address_ = 0x631f60, static default_instance_ = 0x6324c0}
(gdb) p person1->                                            <---------------tab tab,两次tab,代码补全功能
ByteSize                         SharedCtor                       clear_email                      has_address                      mutable_name                     set_email
Clear                            SharedDtor                       clear_has_address                has_age                          mutable_phone                    set_has_address
CopyFrom                         Swap                             clear_has_age                    has_id                           mutable_unknown_fields           set_has_age
GetCachedSize                    _cached_size_                    clear_has_id                     has_name                         name                             set_has_id
GetMetadata                      _has_bits_                       clear_has_name                   id                               name_                            set_has_name
InitAsDefaultInstance            _unknown_fields_                 clear_id                         id_                              operator=                        set_id
IsInitialized                    add_email                        clear_name                       kAddressFieldNumber              phone                            set_name
MergeFrom                        add_phone                        clear_phone                      kAgeFieldNumber                  phone_                           unknown_fields
MergePartialFromCodedStream      address                          default_instance                 kEmailFieldNumber                phone_size                       ~Person
New                              address_                         default_instance_                kIdFieldNumber                   release_address
Person                           age                              descriptor                       kNameFieldNumber                 release_name
SerializeWithCachedSizes         age_                             email                            kPhoneFieldNumber                set_age
SerializeWithCachedSizesToArray  clear_address                    email_                           mutable_address                  set_allocated_address
SetCachedSize                    clear_age                        email_size                       mutable_email                    set_allocated_name
(gdb) p person1->ByteSize()                                  <---------------print,打印
$4 = 88
(gdb) n                                                      <---------------next,单条语句执行
45    writer.stopWriter();
(gdb) n                                                      <---------------next,单条语句执行
47    GeneralBuf::PersonProtoReader reader;
(gdb) n                                                      <---------------next,单条语句执行
48    reader.startReader(filename);
(gdb) c                                                      <---------------continue,继续运行程序,下一个断点处停止
Continuing.
version : 20191001
cnt : 1Breakpoint 2, main (argc=1, argv=0x7fffffffdc88) at /home/yngzmiao/github/protobuf-parser-tool/c++/example_person.cpp:55
55    person->PrintDebugString();
(gdb) c                                                      <---------------continue,继续运行程序,下一个断点处停止
Continuing.
id: 100000
name: "zhangsan"
age: 20
email: "123456@qq.com"
email: "234567@qq.com"
phone {number: "987654"type: MOBILE
}
phone {number: "876543"type: HOME
}
address {country: "china"detail: "beijing"
}
[Inferior 1 (process 3734) exited normally]
(gdb) q                                                      <---------------quit,退出GDB
yngzmiao@yngzmiao-virtual-machine:~/github/protobuf-parser-tool/c++/build$

最基本的GDB命令

上文使用的是最基本的GDB命令,下面进行总结:

命令 全称 解释
l list 查看源码
b break 设置断点
r run 运行程序,在断点处停止
n next 单条语句执行
c continue 继续运行程序,下一个断点处停止
p print 打印
q quit 退出GDB

其他的GDB命令,会在后面的博文中进行介绍。

【GDB】手把手教你用gdb调试程序(超清晰流程)相关推荐

  1. 华为语音解锁设置_华为手机免费语音转文字功能如何开启?手把手教你如何设置,超赞...

    原标题:华为手机免费语音转文字功能如何开启?手把手教你如何设置,超赞 关于华为手机免费语音转文字功能,相信你也有所了解,但还有很大部份华为手机用户表示:我的手机为什么没有语音转文字的功能. 如果你是华 ...

  2. 手把手教你做第一个RPA机器人流程

    手把手教你做第一个RPA机器人流程 第一步:下载&安装RPA工具 第二步:新建第一个自动化流程 第三步:开始详细配置流程 简单介绍一下艺赛旗RPA界面 开始流程配置 第四步:总结 第一步:下载 ...

  3. 小羊手把手教你gcc gdb makefile

    1. vim编辑hello.c 2. 分别查看下面gcc指令的结果 GCC交叉编译器简介: 最早为GNU C Compiler是GNU推出的功能强大.性能优越的多平台编译器,是GNU的代表作之一; 支 ...

  4. 手把手教你运行YOLOv6(超详细)

    YOLOv6 是美团视觉智能部研发的一款目标检测框架,致力于工业应用.本框架同时专注于检测的精度和推理效率,在工业界常用的尺寸模型中:YOLOv6-nano 在 COCO 上精度可达 35.0% AP ...

  5. 实战案例,手把手教你使用 Tableau 绘制超炫酷可视化图表

    有一种美叫数据的美,Tableau可以让你看到这种数据美,以及探索数据美的可能,如下图表均是由强大的tableau可视化而成的. 喜欢点赞.收藏 使用tableau的优势就在于不需要懂技术,更不需要写 ...

  6. 手把手教你下载VS2022(超详细)

    目录 一.下载 二.安装配置 一.下载 来到下载网址后,我们如下图所示点击Community 2022下载即可,是社区免费版. VS2022下载链接 (去官网下载即可哦,不需要去某些需要收费的网站,就 ...

  7. 【换脸详细教程】手把手教你进行AI换脸:换脸流程及源码详解

    目录 1. 换脸基本原理 2 人脸检测及可视化 3. 人脸轮廓点检测及可视化 4. 人脸图像变换--仿射变换 5. 生成遮罩并直接替换人脸 6. 人脸颜色校正 最近AI换脸貌似比较火爆,就稍微研究了一 ...

  8. 手把手教你用dlv和gdb调试GoLang

    码字不易,转载请附原链,搬砖繁忙回复不及时见谅,技术交流请加QQ群:909211071 无论哪种方式,都要配置证书相关,参考这篇文章:在Mac安装最新gdb的详细教程,含可能遇到的所有坑(网上最新教程 ...

  9. python numpy安装教程_手把手教你搭建机器学习开发环境—Python与NumPy的超简安装教程...

    手把手教你搭建机器学习开发环境Python语言是机器学习的基础,所以,想要入门机器学习,配置好Python的开发环境是第一步.本文就手把手的教你配置好基于Python的机器学习开发环境.超简单!第一步 ...

最新文章

  1. 主成分分析(PCA)Python代码实现
  2. 排序算法 时间复杂度+空间复杂度 总结
  3. 结构风险和经验风险是什么?怎么去平衡它们?
  4. mysql 开仓函数_MySQL函数大全 及用法示例
  5. mysql源码添加一个命令,MySQL ALTER命令
  6. Python selenium巧用Javascript脚本注入解决按钮点选问题
  7. ArcGIS Desktop 10.5 安装实录
  8. idea中mapper.xml的头文件配置
  9. 国内外大数据经典案例研究
  10. 洛谷P2757 [国家集训队]等差子序列
  11. 常用大数据核心技术有哪些?
  12. SCP不会覆盖已有文件
  13. mysql lob字段_数据库的LOB大字段的一些总结
  14. 全球与中国网络连接视频门铃对讲机系统市场深度研究分析报告势
  15. 用Python实现表白代码 抖音最火的整蛊表白小程序如何做出来的
  16. 2009年经典语录雷人总汇
  17. 【SLAM】视觉SLAM:一直在入门,从未到精通
  18. 2016中国IT用户满意度总体保持平稳
  19. [NOTE in progress] Simulation Optimization
  20. Android Native程序crash的一些定位方法简介

热门文章

  1. 共享移动智能办公入口 钉钉10亿加速企业数字化和智能化
  2. 最新ie图标变灰css,网站变灰的CSS代码(兼容火狐、Chrome、IE系浏览器)——w3cdream|前端学习-开发...
  3. python新手怎么兼职-学完python怎么找兼职呢?
  4. 网页添加Live2D,背景线条动漫人物
  5. 聊聊大数据(一)——大数据的存储
  6. 弹性盒子模型属性之flex-grow
  7. UML-----uml建模的分类
  8. CF1369D TediousLee 翻译
  9. linux探测路由器重启,openwrt命令实现网络不通,自动重启路由器,重新拨号或者重启wifi...
  10. QQ聊天 QQ流应该注意的问题