gdb调试技术

gdb调试技术


1使用gdb调试

调试程序
当程序出现运行错误(bug)时,我们需要调试程 序,将错误找出并解决(debug)
参考:《单步调试》(VC下面的调试程序的方法)

调试手段分为两种:
(1) 单步调试:使用调试器,结合断点,观察变 量和内存的值。
(2) 打印调试: 将关键信息用printf等函数输出分析

gdb调试
在Linux使用gdb命令行进行单步调试
准备工作:在compile这一步,添加选项‐g
g++ ‐g main.cpp ‐o helloworld

%.o: %.cpp
[tab]g++ ‐c ‐g‐MMD $< ‐o $@

控制类命令
进入gdb界面后,使用命令来操纵调试过程。 gdb ./helloworld 进入gdb界面
b (break) : 添加断点
r (run): 重头开始运行程序
n (next): 下一步
c (continue): 程序继续运行,直到下一处断点, 或者程序运行结束
q (quit): 退出程序界面
(注:可以输入全称break,也可以只输入b)

添加断点:
b main (加上函数名)
b main.cpp:12 (文件名+行号)
b 12 (当前文件的行号)
b Object::Create (类名+ 成员函数)
显示断点info break
删除断点del break 2 (后面的2是编号)

next 执行下一步
n 执行下一步
n 3 执行下面三步

显示变量/内存
p (print) 显示表达式的值
p a
p a+b
p (Object*)p1‐>a
更特殊的用法,像函数一样调用显示
p ("%d", ‘A’)

显示变量/内存
disp (display) 监视变量(每执行一步都显示),相当于VC下的watch

x 显示内存的值
x/16xb buf
其中,
16: 显示16个单位
x: 以十六进制显示(x d u f s …)
b: 单位是1字节(可选b h w g )
byte, half‐word, word, giant

扫描二维码关注公众号,回复: 9702154 查看本文章

查看帮助
help x
help info
可以查看某个子命令的帮助

小结:
1,gdb调试准备
2,控制类命令
3,查看类命令

2段错误与内存转储

段错误Segment Fault
在Linux下,程序中如果进行了不正确的指针操作, 则程序崩溃、提示"Segment Fault"

如,空指针访问,野指针访问,数组越界访问。。。
int* p = NULL;
*p = 1;
安全的使用指针
错误提示(段错误,core dumped)

段错误的定位
一、如果此错误容易复现,则使用gdb
gdb helloworld
会在发生段错误的地方提示
Program received signal SIGSEGV, Segmentation fault.
0x0804844a in test (p=0x0) at main.cpp:5
5 *p = 12; 此时程序已经异常终止

bt (backtrace) 查看错误时刻的栈信息

内存转储
二、此错误不容易复现
程序长年累月地运行,不知何时发生了段错 误,程序异常关闭。
可以使用“内存转储”手段,来复原查看段 错误发生的位置。

内存转储

  1. 在运行该程序的shell(终端)里运行命令
    ulimit ‐c unlimited
    (注:在shell关闭重启后,要重新运行一次)

  2. 运行程序
    程序发生段错误时,程序退出,同时当发生错误 时的信息转储(dump)到一个core.*文件。

  3. 用gdb来查看发生段错误的代码位置
    gdb helloworld core.***

小结:
1,段错误
2,内存转储

3gdb调试的补充说明

内容提要
(1)什么样的程序是可调试的?
(2)什么场合下适合用gdb调试?什么场合不适 合?

程序中的调试信息
当程序编译时带‐g选项时,程序才可以被调试
实际上,当以‐g选项编译时,编译器将“调试信息” 加在了目标程序里,因此,目标程序的体积将显著 变大。
比较输出的目标程序的体积:
g++ ‐g main.cpp ‐o helloworld
g++ main.cpp ‐o helloworld

那么,如何判断一个程序是否带有“调试信息”呢?
第一种方法: (直接查看)
objdump ‐h helloworld
(注:gcc g++ gdb objdump nm ar ld …是一套工具)
会出现一堆.debug开头的段
第二种方法: gdb helloworld
如果调试信息,会提示:
Reading symbols from helloworld…(no debugging symbols found)…done.

调试信息记录了哪些东西?
‐至少记录了源文件和行号信息

gdb的使用场合
适用的场合:
‐ 单元测试(较短的代码,功能单纯的函数)
‐ 段错误的定位
不太适用的场合:
‐ 大型程序,
-尤其是程序中使用了多线程
‐ 单步调试的时候问题无法复现,只能在正常运 行的时候复现
(我们使用打印调试)

小结:
1,gdb调试的原理
2,gdb与打印调试的场合

学习资源 《C语言/C++学习指南》Linux开发篇

发布了6 篇原创文章 · 获赞 0 · 访问量 67

猜你喜欢

转载自blog.csdn.net/qq_46165724/article/details/104761162