【给女朋友讲C++】C++的调试之gdb

2024-08-29 23:20
文章标签 c++ 调试 gdb 女朋友

本文主要是介绍【给女朋友讲C++】C++的调试之gdb,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1 什么是gdb
  • 2 core dump
    • 2.1 打开core dump功能
    • 2.2 修改core dump文件保存的路径
    • 2.3 使用gdb分析core文件
  • 3 gdb常用命令
    • 3.1 为了更好的使用gdb调试,需要设置-g编译选项
      • 3.1.1 命令行方式编译:
      • 3.1.2 cmake方式
    • 3.2 gdb的help
    • 3.3 gdb与可执行程序相关的命令
      • 3.3.1 可执行程序未执行
      • 3.3.2 可执行程序已经执行
    • 3.4 gdb基础命令
  • 4 参考

1 什么是gdb

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果是在windows上使用vs调试也是不错的选择。

工作中一般都是用gdb来分析core dump文件的多,如果core dump文件分析不出来,再用gdb单步执行进行分析。对于程序的逻辑和算法一般用log会更为直观一些,当然也会gdb + log来联合分析问题。

2 core dump

当程序在运行过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫core dump。 我们可以认为core dump是”内存快照”,但实际上,除了内存信息之外,还有些关键的程序运行状态也会同时dump下来, 例如寄存器信息(包括程序指针,栈指针等),内存管理信息,其他处理器和操作系统状态和信息。

2.1 打开core dump功能

  • 在终端中输入命令 ulimit -c,输出结果为0,说明默认是关闭core dump的,即当程序异常终止时,也不会生成core dump文件;
  • 我们可以使用命令 ulimit -c unlimited 来开启core dump功能;
  • 如果想需要永久生效,可以修改文件/etc/security/limits.conf文件,在其中增加一行:
# /etc/security/limits.conf
#
#Each line describes a limit for a user in the form:
#
#<domain>       <type>  <item>  <value>*             soft    core    unlimited

2.2 修改core dump文件保存的路径

  • 默认生成的core dump文件保存在可执行文件所在的目录,文件名为core
  • 通过修改 /proc/sys/kernel/core_uses_pid 文件可以控制生成core文件名时是否自动加上pid号;
    • 例如,echo 1 > /proc/sys/kernel/core_used_pid,生成的core文件名将会变成core.pid,其中pid表示该进程的PID;
  • 还可以通过修改**/proc/sys/kernel/core_pattern**来控制生成core文件保存的位置以及文件格式;
    • 例如,可以用echo “/tmp/corefile-%e-%p-%t” > /proc/sys/kernel/core_pattern设置生成的core文件保存在/tmp/corefile目录下,文件名格式为core-命令名-pid-时间戳。

2.3 使用gdb分析core文件

使用如下命令打开core文件

gdb [exec file] [core file]

然后执行bt命令查看堆栈,一般就可以根据提示看出来问题,因为往往都是非法访问内存。如果不行,就需要使用更多的gdb命令,下面介绍。

3 gdb常用命令

3.1 为了更好的使用gdb调试,需要设置-g编译选项

为了更好的使用gdb调试程序,在使用gcc/g++编译器的时候需要加上**-g**参数。如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。

3.1.1 命令行方式编译:

g++ -g -o test test.cpp

3.1.2 cmake方式

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")

3.2 gdb的help

$ gdb
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 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".
(gdb) help
List of classes of commands:aliases -- Aliases of other commands.
breakpoints -- Making program stop at certain points.
data -- Examining data.
files -- Specifying and examining files.
internals -- Maintenance commands.
obscure -- Obscure features.
running -- Running the program.
stack -- Examining the stack.
status -- Status inquiries.
support -- Support facilities.
tracepoints -- Tracing of program execution without stopping the program.
user-defined -- User-defined commands.Type "help" followed by a class name for a list of commands in that class.
Type "help all" for the list of all commands.
Type "help" followed by command name for full documentation.
Type "apropos word" to search for commands related to "word".
Type "apropos -v word" for full documentation of commands related to "word".
Command name abbreviations are allowed if unambiguous.
  • gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果要看种类中的命令,可以使用help
    命令,如:help breakpoints,查看设置断点的所有命令。也可以直接help 来查看命令的帮助。
  • gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,命令的前几个字符应该要标志着一
    个唯一的命令,在Linux下,你可以敲击两次TAB键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。

3.3 gdb与可执行程序相关的命令

3.3.1 可执行程序未执行

gdb <program>        # rogram也就是你的执行文件
gdb --args <program> arg1 arg2 arg3  # arg1,arg2,arg3为命令行参数
gdb <program> core   # core是程序非法执行后core dump后产生的文件

在以gdb 等方式启动gdb后,gdb会在PATH路径和当前目录中搜索的源文件。如要确认gdb是否读到源文
件,可使用l或list命令,看看gdb是否能列出源代码。

  1. 也可以在gdb启动后设置命令行参数
set args 可指定运行时参数。(如:set args 10 20 30 40 50)
show args 命令可以查看设置好的运行参数。
  1. 运行环境
path <dir> 可设定程序的运行路径。
show paths 查看程序的运行路径。
set environment varname [=value] 设置环境变量。如:set env USER=hchen
show environment [varname] 查看环境变量。
  1. 工作路径
cd <dir> 相当于shell的cd命令。
pwd 显示当前的所在目录。
  1. 程序的输入输出
run > outfile   # 运行程序,将输出重定向到outfile

3.3.2 可执行程序已经执行

gdb <program> <PID>  # 如果你的程序已经启动,那么你可以指定这个程序运行时的进程ID,gdb会自动attach上去,并调试他。# 另一种方式:先用gdb <program>关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进
程。

3.4 gdb基础命令

r   # 等于run,运行程序
b   # 等于break,设置断点# 可选的参数有:# 方法名,如C++中可以使用class::function或function(type,type)格式来指定函数名。或者filename:function# 行号,如filename:linenum
info break # 查看断点
clear # 清除所有的断点,只是让断点失效,还会保留其他相关信息。# 可选的参数有:方法名,行号,断点号
delete [breakpoints] [range...]  # 删除指定的断点,breakpoints为断点号。如果不指定断点号,则表示删除所有的断点。range 表示断点号的范围(如:3-7)。其简写命令为d。
disable [breakpoints] [range...]  # disable所指定的停止点,breakpoints为停止点号。如果什么都不指定,表示disable所有的停止点。简写命令是dis
enable [breakpoints] [range...]  # enable所指定的停止点,breakpoints为停止点号。
c   # 等于continue,恢复程序运行,直到结束
s   # 等于step,单步执行程序,遇到函数,会进入函数
n   # 等于next,和step的不同时,遇到函数不会进入
finish  # 运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息
bt       # 等于backtrace,查看堆栈信息
f <n>    # 等于frame <n>,查看某一层的堆栈信息
up <n>   # 表示向栈的上面移动n层,可以不打n,表示向上移动一层。 
down <n> # 表示向栈的下面移动n层,可以不打n,表示向下移动一层。
info f   # 等于info frame,这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等
list  # 显示当前行后面的源程序。可选的参数有行号,方法名
dir <dirname ... >  # 等于directory <dirname ... >, 加一个源文件路径到当前路径的前面。如果你要指定多个路径,UNIX下你可以使用“:”,Windows下你可以使用“;”
directory  # 清除所有的自定义的源文件搜索路径信息。
show directories # 显示定义了的源文件搜索路径。
p    # 等于print, 可以打印变量,表达式的值

4 参考

  1. Linux下core dump
  2. GDB完全中文手册.pdf
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

这篇关于【给女朋友讲C++】C++的调试之gdb的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

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

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

Java服务实现开启Debug远程调试

《Java服务实现开启Debug远程调试》文章介绍如何通过JVM参数开启Java服务远程调试,便于在线上排查问题,在IDEA中配置客户端连接,实现无需频繁部署的调试,提升效率... 目录一、背景二、相关图示说明三、具体操作步骤1、服务端配置2、客户端配置总结一、背景日常项目中,通常我们的代码都是部署到远程

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数