Linux C++ 开发6 - GDB调试入门指南

2024-09-01 17:28

本文主要是介绍Linux C++ 开发6 - GDB调试入门指南,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 1. GDB的介绍
    • 1.1. 什么是GDB?
    • 1.2. 安装GDB
  • 2. 编译带调试信息的程序
    • 2.1. 命令行编译
    • 2.2. makefile编译
    • 2.3. cmake编译
  • 3. GDB使用流程
    • 3.1. 测试源代码准备
    • 3.2. 启动GDB
    • 3.3. 查看源码
    • 3.4. 运行程序
    • 3.5. 设置断点
    • 3.6. 单步执行
    • 3.7. 查看变量
  • 4. GDB常用命令

与Windows下C++开发相比,Linux下C++开发最大的困难就是程序的调试。

Windows下,Visual Studio系列的IDE(Visual Studio 2010/2013/2015/2017/2019/2022)都内置了C++调试引擎,可通过可视化的界面完成调试操作:在IDE里设置调试断点,然后按F5就可以开始调试了,简单又方便。而且功能强大,支持 断点调试、变量查看、单步执行、堆栈跟踪等等。

Linux就没有这么幸运了,没有这么强大可用的可视化工具。Linux下C++的调试,主要又两种方式:

  • 日志打印: 在代码中通过log打印相关的调试信息,程序运行后分享log的数据进行调试。如果你是开发阶段,或者你的程序是一个简单的Demo,也可以直接用std::cout(C++)或printf(C语言)来打印调试信息。
  • GDB调试: GDB是GNU DeBug的缩写,是Linux的调试器。你需要了解GDB工具的常见用法和调试手段。

本文将带领大家一起入门Linux下GDB的调试方法。

1. GDB的介绍

1.1. 什么是GDB?

GDB的全称是GNU DeBugger,它是一个由GNU项目开发的开源调试器,用于调试C和C++程序。GDB允许开发者检查程序的执行过程,设置断点,查看变量值,以及执行其他调试任务,如分析程序崩溃的原因。

GDB支持多种编程语言,包括C、C++、Objective-C、Fortran、Pascal等。通过GDB,开发者可以更有效地诊断和修复代码中的错误,提高开发效率。

1.2. 安装GDB

《Linux C++ 开发1 - 搭建C++开发环境》一文,我们介绍了Linux C++开发环境的搭建,其中包括了安装GDB的步骤。如果你的系统(Ubuntu)还未安装gdb,可以通过以下命令来安装:

# 安装gdb
sudo apt install gdb
# 检查gdb是否安装成功
gdb --version

2. 编译带调试信息的程序

为了能使用GDB进行调试,需要在编译时包含调试信息(即在编译时能够生成调试符号表symbols)。使用-g-ggdb选项进行编译:

2.1. 命令行编译

# -g选项:生成标准的调试信息
g++ -g -o my_program my_program.cpp
# -ggdb选项:生成gdb专用的调试信息
g++ -ggdb -o my_program my_program.cpp
  • -g 选项用于生成标准的调试信息,这些信息可以被多种调试器使用,该选项生成的调试信息符合DWARF(Debugging With Attributed Record Formats)标准,DWARF这是一种通用的调试信息格式。
  • -ggdb 选项专门为GDB生成调试信息。它生成的调试信息可能包含一些GDB特有的扩展,这些扩展可能不适用于其他调试器,不过使用-ggdb选项可以确保生成的调试信息对GDB是最优的。

2.2. makefile编译

# 构建的最终目标 Iterator(可执行文件)
Iterator:Iterator.o Company.o Person.og++ -o Iterator Iterator.o Company.o Person.o
# 构建目标 Iterator.o
Iterator.o:Iterator.cppg++ -g -c Iterator.cpp
# 构建目标 Company.o
Company.o:Company.cppg++ -g -c Company.cpp
# 构建目标 Person.o
Person.o:Person.cppg++ -g -c Person.cpp# 申明clean为伪目标
.PHONY: clean
clean:rm -f *.o Iterator

注意:

  • 是在编译成目标文件.o的时候加上-g选项,而不是在链接的时候加上-g选项。
  • cpp源代码参见 https://gitee.com/spencer_luo/iterator/tree/master/

2.3. cmake编译

# 设置构建类型: Debug/Release
set(CMAKE_BUILD_TYPE Debug)
# 设置编译选项
if(CMAKE_BUILD_TYPE STREQUAL "Debug")# Debug模式,编译是需要保留调试符号表set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")# Release模式,编译时优化代码,优化选项:-O2set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
endif()

3. GDB使用流程

3.1. 测试源代码准备

demo02.cpp:

#include <iostream>int add(int a, int b)
{return a + b;
}int division(int a, int b)
{return (int)(a / b);
}int main()
{std::string name = "Spencer";std::cout << "Hello, " << name << "!" << std::endl;int a = 5;int b = 0;int c = division(a, b);int d = add(c, 20);std::cout << "d = " << d << std::endl;return 0;
}

Iterator:

参见源码仓库: https://gitee.com/spencer_luo/iterator/tree/cmake/

3.2. 启动GDB

使用以下命令启动GDB并加载要调试的程序:

# 正常启动,program_name为带符号表的可执行程序
gdb program_name
# quiet, 表示不打印gdb版本等信息,界面较为干净;
gdb -q program_name

测试如下:

gdb ./demo02.out 
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 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:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.<http://www.gnu.org/software/gdb/documentation/>.--Type <RET> for more, q to quit, c to continue without paging--<http://www.gnu.org/software/gdb/documentation/>.--Type <RET> for more, q to quit, c to continue without paging--
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./demo02.out...<http://www.gnu.org/software/gdb/documentation/>.<http://www.gnu.org/software/gdb/documentation/>.<http://www.gnu.org/software/gdb/documentation/>.--Type <RET> for more, q to quit, c to continue without paging----Type <RET> for more, q to quit, c to continue without paging--
--Type <RET> for more, q to quit, c to continue without paging--
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./demo02.out...
(gdb)
(gdb) q
gdb -q ./demo02.out
Reading symbols from ./demo02.out...
(gdb)
(gdb) q

3.3. 查看源码

list(缩写l): 查看源程序代码,默认显示10行,按回车键继续看余下的。

file

3.4. 运行程序

run(缩写r) :运行程序直到遇到 结束或者遇到断点等待下一个命令。

file

我们直接运行./demo02.out看到程序崩溃了,但是不知道崩溃在哪一行。但是通过gdb一运行,立马就看出来了。

3.5. 设置断点

break n(缩写b n) :在第n行设置断点。

file

3.6. 单步执行

使用 continue、step、next命令。
在这里插入图片描述

3.7. 查看变量

使用 print、info locals命令。

file

4. GDB常用命令

更多GDB常用命令,将在下一节进行讲解,敬请期待…


大家好,我是陌尘。

IT从业10年+, 北漂过也深漂过,目前暂定居于杭州,未来不知还会飘向何方。

搞了8年C++,也干过2年前端;用Python写过书,也玩过一点PHP,未来还会折腾更多东西,不死不休。

感谢大家的关注,期待与你一起成长。



【SunLogging】
扫码二维码,关注微信公众号,精彩内容

这篇关于Linux C++ 开发6 - GDB调试入门指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1127587

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Linux云服务器手动配置DNS的方法步骤

《Linux云服务器手动配置DNS的方法步骤》在Linux云服务器上手动配置DNS(域名系统)是确保服务器能够正常解析域名的重要步骤,以下是详细的配置方法,包括系统文件的修改和常见问题的解决方案,需要... 目录1. 为什么需要手动配置 DNS?2. 手动配置 DNS 的方法方法 1:修改 /etc/res

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他