本文共 2668 字,大约阅读时间需要 8 分钟。
什么是GDB?
GNU项目中的调试器(gnu debuger),能够跟踪程序的执行,也能恢复程序崩溃前的状态。为什么需要GDB?
软件不是一次性开发完成的(是软件就有bug,是程序就有问题),调试是软件开发过程中不可或缺的技术(调试工具很重要)。GDB的常规应用
GDB和addr2line工具的本质区别
addr2line是静态分析工具,关注的是程序文件;GDB是动态分析工具,关注的是进程。直接启动
动态连接
test.c
#include#include extern int* g_pointer;extern void func();void test_1(){ printf("test_1() : %p\n", test_1);}void test_2(){ printf("test_2() : %p\n", test_2);}void test_3(){ printf("test_3() : %p\n", test_3);}int main(int argc, char *argv[]){ typedef void(TFunc)(); TFunc* fa[] = {test_1, test_2, test_3}; int i = 0; printf("main() : begin...\n"); for(i=0; i 1); } printf("g_pointer = %p\n", g_pointer); func(); printf("main() : end...\n"); return 0;}
func.c
#includeint* g_pointer;void func(){ *g_pointer = (int)"D.T.Software"; return;}
采用如下方式进行编译
gcc -g test.c func.c -o test.out
直接运行test.out会出现段错误,下面使用GDB进行bug定位:
方式一:
为了在发生段错误时生成core文件,需要执行如下命令:ulimit -c unlimited
接下来执行应用程序: ./test.out
使用GDB进行调试: gdb ./test.out core
方式二:
gdb
启动 file test.out
载入目标程序 set args lmeon
设置命令行参数 run
执行目标程序 如果需要暂停程序执行,ctrl+c
即可。输入continue
或者按下enter键即可恢复程序执行。
方式三:
可以使用ps aux
获取已经运行进程的pid,打开gdb时需要root权限,可以使用sudo命令。
软件断点:由非法指令实现(软件实现)
硬件断点:由硬件特性实现(数量有限)
数据断点:由硬件特性实现(数量有限)
通过函数名设置断点
break func_name [ if var == name ](永久性断点)
tbreak func_name [ if var == name ](临时断点,只会暂停一次,条件断点只能跟踪函数参数的值,而不能跟踪函数内的局部变量,只有运行到当前函数后打断点才可以跟踪局部变量的值)
通过文件名行号设置断点
break file_name:line_num [ if var = name ]
break file_name:line_num [ if var = name ]
软件断点的相关操作
调试时的常用操作
run直接执行可执行程序,start在执行可执行程序后立即暂停(停在main函数的第一行)。
show can-use-hw-watchpoint
查看支持的硬件断点数 GDB小结
数据断点
watch var_name
GDB中可以检查任意内存区域中的数据。
命令语法: x /Nuf expression
示例:
x /4bx 0x804a024
x命令中参数u对应的单位
GDB中的打印格式
示例:判断系统大小端
编程实验:变量断点和内存查看
#include#include #include int g_var = 0;void* thread_func(void* args){ sleep(5); g_var = 1;}int main(){ int i = 0; pthread_t tid = 0; pthread_create(&tid, NULL, thread_func, NULL); for(i=0; i<10; i++) { printf("g_var = %d\n", g_var); sleep(1); }}
注意:编译的使用使用的命令为
gcc -g -pthread watch.c