目录
🥑在 Linux 下我们可以通过 gcc 进行编译,但与 vs 相比若想对代码进行调试,我们还需要学会使用调试器 gdb 。
🥑我们都知道程序的发布方式有两种,release 版本和 debug 版本,而 release 版本是无法进行调试的,在 VS 之中默认为 debug 版本,并且可以通过选取来直接更改程序的不同版本。
🥑但在 Linux gcc/g++ 出来的二进制程序,默认是 release 模式,因此无法调试。若想转换成 debug 版本,则必须在源代码生成二进制程序的时候, 加上 -g 选项。
gcc -g -o text text.c
🥑同时我们也注意到,debug 版本的可执行程序明显占的空间较大,这是因为 release 版本是最终用户在使用的版本,且用户根本不需要对文件进行调试,为了节约空间占比,release 版本便不会加上文件的调试信息,这也是为什么 release 版本下无法进行调试的原因。
-rwxrwxr-x 1 Alpaca Alpaca 9544 Feb 3 11:56 text.debug-rwxrwxr-x 1 Alpaca Alpaca 8384 Feb 3 11:57 text.release
🥑当我们拿到 debug 版本的可执行文件之后就可以进行调试了。直接 gdb + 可执行文件名 就可以打开调试器了。
[Alpaca@VM-12-9-centos myfile]$ gdb text.debug //gdb + 文件名GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7Copyright (C) 2013 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later 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-redhat-linux-gnu".For bug reporting instructions, please see: ...Reading symbols from /home/Alpaca/myfile/text.debug...done.(gdb) //进入后的命令行
🥑l + 行号(中间要有空格): 从该行开始向下打印10行。若代码过长再按回车会自动重复上一个指令进行操作。
(gdb) l 11#include2#include34void plus(int* p)5{6*p *= 2;7}89int main()10{(gdb) //再按一次回车11int count = 0;12while (1)13{14printf("%d\n", count);15count++;16plus(&count);17}18return 0;19}(gdb)
🥑r :开始调试 ,与VS中的F5效果相同,若程序非死循环或过程中无断点则会直接执行到程序结束。
断点
打断点
🥑 d + 行号 :在该行打断点。
🥑 d + 函数名 : 在该函数有效行处打上断点。
(gdb) b 11 //以行号打断点Breakpoint 3 at 0x40054e: file text.c, line 11.(gdb) b main //找函数打断点Breakpoint 1 at 0x40054e: file text.c, line 11.
查看、删除断点
🥑 info b :查看所有断点信息。
🥑 d + 断点编号 :删除断点
(gdb) info bNum Type Disp Enb Address What3 breakpoint keep y 0x000000000040054e in main at text.c:114 breakpoint keep y 0x0000000000400555 in main at text.c:145 breakpoint keep y 0x0000000000400569 in main at text.c:15
(gdb) d 4(gdb) info bNum Type Disp Enb Address What3 breakpoint keep y 0x000000000040054e in main at text.c:115 breakpoint keep y 0x0000000000400569 in main at text.c:15
断点使能
🥑 disable : 禁用断点。(当禁用断点后再次运行直到程序结束才会停止)
🥑 enable : 使用断点。
🥑 n :逐过程调试。(类似于VS中的F10,若遇到函数调用不会进入到函数之中)
🥑 s :逐语句调试。(类似于VS中的F11,会进入到函数之中继续调试)
//逐语句Breakpoint 3, main () at text.c:1111int count = 0;(gdb) n14printf("%d\n", count);(gdb) n0Breakpoint 5, main () at text.c:1515count++;(gdb) n16plus(&count);(gdb) 17}//逐语句Breakpoint 5, main () at text.c:1515count++;(gdb) 16plus(&count);(gdb) plus (p=0x7fffffffe42c) at text.c:66*p *= 2;(gdb) 7}(gdb) main () at text.c:1717}
显示数据
🥑 p + 变量名 :打印出该变量当前的值。
🥑 display + 变量名:跟踪查看一个变量,每次停下来都显示它的值。
🥑 undisplay + 编号 : 取消对变量的跟踪查看。
(gdb) p count$4 = 2(gdb) display count3: count = 2(gdb) undisplay 3
其他指令
🥑 c :从一个断点处直接执行到下一个断点。
🥑 set var:修改变量的值。
🥑 finish : 执行完一个函数。
🥑 until + 行号:跳至该行。
🥑 bt :查看各级函数调用及参数。
🥑 quit :退出gdb。
🥑在Linux下以下的三条语句会产生三种不一样的结果。
printf("hello world\n"); //正常打印后暂停一秒sleep(1); printf("hello world"); //暂停了一秒后语句和提示符一起打印出来 sleep(1); printf("hello world\r"); //无语句打印 sleep(1);
hello world[Alpaca@VM-12-9-centos myfile]$ hello world[Alpaca@VM-12-9-centos myfile]$[Alpaca@VM-12-9-centos myfile]$
行缓冲区
🥑在字符串被打印出来之前,会将其先加载到行缓冲区之中,但不是立刻就会打印出来。因此在第二条语句时,语句还没有打印出来系统就暂停了一秒钟,之后行缓冲区刷新,将之前的内容都打印出来, 因此第二个语句才会是先暂停一秒再打印。又因为提示符是跟随光标打印的,所以便跟在语句之后打印。
🥑我们都知道 \n 为换行符,而 \r 又被称为回车,会将光标会到本行的最开始。当我们使用 \n 便会强行刷新行缓冲区,使之前的数据被打印出来。而第三个语句之所以没有打印出语句则是因为 \r 使得光标回到本行开头,提示符从头开始打印将原来要打印出来的语句覆盖掉了,所以没有语句显示出来。
🥑若使用fflush对缓冲区进行刷新的话,便能够看到语句打印出来一秒钟后,就被系统的提示符覆盖打印了。
#include #include int main(){ printf("hello world\r"); fflush(stdout); sleep(1); return 0;}
小程序
🥑通过上面第三个语句的启发,我们可以写出一个类似于进度条的小程序,通过每次重复覆盖打印,得到进度条在持续增长的效果。
#include#include#include #define SIZE 101int main(){ int i = 0; char s[SIZE]; //转换成重复打印一个数组 memset(s,0,SIZE*sizeof(char)); //对数组初始化 const char *lable ="|/-\\"; while(i<=100) { if(i!=100) { s[i] = '>'; //i指向最高一位,作为箭头 } printf("[%-100s][%3d%%][%c]\r",s,i,lable[i%4]); //把数组对其打印出来,并附上其他观赏性信息 fflush(stdout); //每次刷新缓冲区 s[i++] = '='; //进度条延长 usleep(100000); } printf("\n"); return 0; }
🥑好了这次调试器 gdb 及 '\r' 的介绍就到这里结束了,关注博主共同进步!!
来源地址:https://blog.csdn.net/Lin_Alpaca/article/details/128863346