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

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
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值