单品商城网站源码,wordpress问答插件中文免费版,南昌地宝网首页,翻译网页gdb调试教程
快速入门
要想快速入门gdb调试#xff0c;可以直接翻阅基本案例#xff1a;采内存
介绍
GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c程序员#xff0c;gdb是必不可少的工具
…gdb调试教程
快速入门
要想快速入门gdb调试可以直接翻阅基本案例采内存
介绍
GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c程序员gdb是必不可少的工具
常用指令
shell 指令
指令用法介绍gdbgdb ${exe}对生成的可执行文件进行调试gdb -qgdb -q ${exe}对生成的可执行文件进行调试表示不打印gdb版本信息界面较为干净
gdb指令
指令用法介绍断点设置breakbreak Linebrbreak{Line}brbreak Linebrbreak{func}可以对行号和函数进行设置断点程序运行runrun / r首次运行程序运行到第一个断点continuecontinue / c继续运行程序运行到下一个断点nextnext / n单步跳过执行一步程序遇到函数直接完成函数操作不会进入函数stepstep / s单步进入执行一步程序遇到函数会进入untiluntil / u ${Line}跳出循环体并跳到循环体外部的某一行变量查看printprint 变量打印变量的值whatiswhatis 变量打印变量的类型quitquit / q退出可视化layout src调试的时候同时显示源代码窗口但是必须run之后才会显示
基本案例采内存
0. 源码
本案例以下文段错误采内存源码进行介绍如何进行gdb调试。
通常在复杂程序调用中指针的操作容易导致编程人员对内存空间的使用造成困扰和混乱因此指针操作是导致内存异常问题最为常见的因素也是最难定位的因素。
源代码如下
在本案例中main函数里的my_user指针在addUser函数里进行资源申请。虽然成功申请到了堆中的空间。但是因为my_user是作为参数传入因此在函数返回时my_user又重新指向了NULL而非堆上的空间地址导致运行发生段错误。
#include stdio.h
#include stdlib.htypedef struct User {int id;int age;
} User;void addUser(User *user, int id, int age)
{user (User *)malloc(sizeof(User));user-id id;user-age age;printf(id %d, age %d\n, user-id, user-age);
}int main()
{printf(gdb demo\n);User *my_user NULL;addUser(my_user, 10, 20);printf(id %d, age %d\n, my_user-id, my_user-age);return 0;
}1. 编译
要想使用gdb调试功能需要在gcc编译器添加-g参数或者在cmake里编译成debug模式。 gcc -g -o main main.c2. 打开gdb调试 gdb main gdb -q main # 表示不打印gdb版本信息界面较为干净3. gdb 设置断点
breakinfo breakpoints
# 使用 break 或者 b 进行设置断点。
# 可以对函数进行打点或者对代码行进行打点。
# 我们可以使用info breakpoints查看当前所有的断点信息
(gdb) b addUser
Breakpoint 1 at 0x752: file gdb_test.c, line 11.
(gdb) b 13
Breakpoint 2 at 0x769: file gdb_test.c, line 13.
(gdb) b 20
Breakpoint 3 at 0x7aa: file gdb_test.c, line 20.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000000752 in addUser at gdb_test.c:11
2 breakpoint keep y 0x0000000000000769 in addUser at gdb_test.c:13
3 breakpoint keep y 0x00000000000007aa in main at gdb_test.c:20 4. 运行
runcontinuenextstep
# 当我们设置完断点进行调试的时候首先要执行run函数开启程序进程run会执行到第一个断点位置
# 然后我们可以执行next 或者 continue 或者 step进行推进程序
# continue: 运行到下一个断点
# next: 单步跳过执行一步程序遇到函数直接完成函数操作不会进入函数
# step: 单步进入执行一步程序遇到函数会进入
(gdb) run
Starting program: /home/rodney/ProjectCode/Cproject/C_coding/gccggdb_block/bug1/main
gdb demoBreakpoint 3, main () at gdb_test.c:20
20 User *my_user NULL;
(gdb) n
22 addUser(my_user, 10, 20);
(gdb) c
Continuing.Breakpoint 1, addUser (user0x0, id10, age20) at gdb_test.c:11
11 user (User *)malloc(sizeof(User));(gdb) c
Continuing.Breakpoint 2, addUser (user0x555555756420, id10, age20) at gdb_test.c:13
13 user-age age;(gdb) n
14 printf(id %d, age %d\n, user-id, user-age);
(gdb) n
id 10, age 20
15 }
(gdb) n
main () at gdb_test.c:23
23 printf(id %d, age %d\n, my_user-id, my_user-age);
(gdb) nProgram received signal SIGSEGV, Segmentation fault.
0x00005555555547cc in main () at gdb_test.c:23
23 printf(id %d, age %d\n, my_user-id, my_user-age);
从上文可以看出是23行打印发生了报错那么如何确定23行的打印发生了什么具体错误可以使用print和whatis进行打印显示。
5. 打印和显示变量信息
print 打印变量的值whatis 打印变量的类型
# 从打印的信息可以看出这里my_user是个空指针因此访问出现上文的段错误。
(gdb) whatis my_user
type User *
(gdb) whatis my_user-id
type int
(gdb) print my_user
$1 (User *) 0x0
(gdb) print my_user-id
Cannot access memory at address 0x0