初窥gdb - 01
来源:互联网 发布:java从右截取字符串 编辑:程序博客网 时间:2024/04/29 15:13
阅读GDB中文手册是非常有必要的,如果有时间,更建议阅读《Debugging with gdb》
但手册类的文档多少有点在罗列命令的感觉,阅读性稍差一些。本人最近在学习c++的gdb调试技巧,顺便记下这些学习笔记,并力求简单易懂,循序渐进
初试GDB
我这里做了个简单的测试实验,从一个简单的程序开始学习调试,以熟悉基本的设置断点和观察点。
源文件:main.cpp
int main(){ int array[3]={0, 0, 0}; //数组初始化 for(int i;i<3;i++) { array[i]=i; //数组赋值 }return 0;}
$ 粗体或者 (gdb) 粗体 表示终端或gdb环境下的命令
1.首先不添加调试信息
进行普通的编译,看看会怎么样:
$ g++ main.cpp
默认输出 a.out 可执行文件
然后启动gdb(命令:gdb <program>):
$ gdb a.out
进入gdb环境
在main函数处添加断点(命令:breakpoint 或 b):
(gdb) b main
Breakpoint 1 at 0x40054a
运行调试:
(gdb) run
Starting program: /home/kevin/workstation/test/gdb/a.out
Breakpoint 1, 0x000000000040054a in main ()
表示停在刚刚设置的断点处
接下来单步执行试试(命令:next 或 n):
(gdb) n
Single stepping until exit from function main,
which has no line number information.
说明没有产生关于行信号的调试信息。
2.加上调试信息:
上一段简单解释了不加调试编译选项的后果,接下来我们加上调试选项-g
$ g++ -g main.cpp
启动gdb:
$ gdb a.out
进入gdb环境
在main函数处添加断点(命令:breakpoint 或 b):
(gdb) b main
Breakpoint 1 at 0x40054e: file main.cpp, line 5. (这里可以看到额外的调试信息,main函数体所在文件,所在行数)
然后我试了一下,调试不运行不能设置观察点!
(gdb) watch array[0]
No symbol "array" in current context.
那么我们就先运行调试:
(gdb) run
Starting program: /home/kevin/workstation/test/gdb/a.out
Breakpoint 1, main () at main.cpp:5
5 {
这里表示程序中断在main函数的函数体内开始的地方
接着我们为数组array的三个元素各自设置一个观察点:
(gdb) watch array[0]
Hardware watchpoint 2: array[0]
(gdb) watch array[1]
Hardware watchpoint 3: array[1](gdb) watch array[2]
Hardware watchpoint 4: array[2]
由于观察点和断点类似,因此这里从Hardware watchpoint 2开始而不是Hardware watchpoint 1
接下来单步执行(命令: next 或者 n):
(gdb) n
6 int array[3]={0, 0, 0};
6表示行号
继续单步:
(gdb) n
Hardware watchpoint 2: array[0]
Old value = 4195760
New value = 0
0x0000000000400564 in main () at main.cpp:6
6 int array[3]={0, 0, 0};
数组初始化,观察点发生变化,值从未初始化值4195760变成初试化值0
继续单步:
(gdb) n
Old value = 4195408
New value = 0
main () at main.cpp:8
8 for(int i;i<3;i++)
这里初始化只显示了array[0]和array[2]的值发生了变化,至于原因并非本文重点,我尝试在附录中进行说明,这里先不提,但至少可以初步推断,在未初始化的时候,array[1]的值就为0。
继续单步:
(gdb) n10 array[i]=i;
(gdb) n
8 for(int i;i<3;i++)
(gdb) n
10 array[i]=i;
(gdb) n
Hardware watchpoint 3: array[1]
Old value = 0
New value = 1
main () at main.cpp:8
8 for(int i;i<3;i++)
(gdb) n
10 array[i]=i;
(gdb) n
Hardware watchpoint 4: array[2]
Old value = 0
New value = 2
main () at main.cpp:8
8 for(int i;i<3;i++)
13 return 0;
(gdb) n
(gdb) n
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
Watchpoint 3 deleted because the program has left the block in
which its expression is valid.
Watchpoint 4 deleted because the program has left the block in
which its expression is valid.
运行结束。
退出GDB:
<ctl> + d
到此为止,我们熟悉了基本的设断点和观察的用法,这里断点设置以函数名作为参数(main)当然还可有其他变种,比如断行号等,待大家自己尝试。
附录:
1.验证未初始化的数组array的各项元素的值
修改源码:main.cpp
#include<iostream>using std::cout;using std::endl;int main(){int array[3]; //这里不进行初始化for(int i;i<3;i++){ cout<<array[i]<<endl; //显示数组}return 0;}
$ g++ main.cpp
$ ./a.out
4196672
0
4196240
可见array[1]的确为0 。
- 初窥gdb - 01
- 初窥gdb - 02
- GDB
- gdb
- GDB
- GDB
- gdb
- GDB
- Gdb
- GDB
- gdb
- gdb
- GDB
- GDB
- gdb
- gdb
- gdb
- GDB
- 基于Node的PetShop,oauth2认证RESTful API
- Selenium webdriver 在IE下定位找不到元素的问题
- iOS VoiceOver Programming Guide
- Swift 学习笔记(三)删除 Main.storyboard 和 LaunchScreen.storyboard
- PHP四种传参方式
- 初窥gdb - 01
- android viewpager 学习使用总结
- JAVA语言运算符
- Leetcode-populating-next-right-pointers-in-each-node
- VoiceOver经验
- Swagger+Spring MVC框架学习分享
- 不再以讹传讹,GET和POST的真正区别
- Android开发中,那些让你觉得相见恨晚的方法、类或接口
- [leetcode] 100. Same Tree