【Linux基础开发工具 (七)】Git 版本管理全流程与 GDB / CGDB 调试技巧

【Linux基础开发工具 (七)】Git 版本管理全流程与 GDB / CGDB 调试技巧

在这里插入图片描述


🎬 个人主页艾莉丝努力练剑
专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:

在这里插入图片描述

文章目录


前情提示

1 Git的文件冲突:两人改同一个文件造成远程和本地仓库不同步

在这里插入图片描述

2 工作区

在这里插入图片描述

3 三板斧

4 调试的本质是什么

在这里插入图片描述

在这里插入图片描述

6 ~> Git版本控制器

前言(看过Git专栏的uu可以跳过这部分啦)

艾莉丝已经把【Git版本控制器】这个板块内容都整理成博客啦,所以Linux主线专栏这里我们就寥寥几笔,直接带过。

专栏链接:详解Git原理与使用

艾莉丝把此专栏的链接都挂在下面了,大家可以根据实际需要乘坐【传送门】哦!

【Git:基本操作】深度解析Git:从初始Git到熟悉基本操作

【Git:分支管理】Git
分支管理完全指南:从创建、合并到冲突解决


【Git:深度解析Git远程操作和标签管理】从克隆到推送:Git
远程操作与标签管理完全指南


【Git:多人协作】Git多人协作实战:从同分支到多分支工作流

【Git:企业级开发模型】Git企业级Git工作流实战:基于Git
Flow的分支模型与开发流程

6.1 入题:小故事

不知道你工作或学习时,有没有遇到这样的情况:我们在编写各种文档时,为了防止文档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出一个副本,比如:

“报告-vl”
“报告-v2”
“报告-v3”
“报告-确定版”
“报告-最终版”
“报告-究极进化版”

每个版本有各自的内容,但最终会只有一份报告需要被我们使用。

但在此之前的工作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的文件就越来越多,文件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各自都是修改了什么吗?

文档如此,我们写的项目代码,也是存在这个问题的!!!

6.2 版本控制器

为了能够更方便我们管理这些不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让你了解到一个文件的历史,以及它的发展过程的系统。通俗的讲就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也方便多人协同作业。

目前最主流的版本控制器就是Git。Git可以控制电脑上所有格式的文件,例如doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git最重要的就是可以帮助我们管理软件开发项目中的源代码文件!

6.3 Git的历史发展

同生活中的许多伟大事物一样,Git诞生于一个极富纷争大举创新的年代。

Linux内核开源项目有着为数众多的参与者。绝大多数的Linux内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991一2002年间)。到2002年,整个项目组开始启用一个专有的分布式版本控制系统BitKeeper来管理和维护代码。

到了2005年,开发BitKeeper的商业公司同Linux内核开源社区的合作关系结束,他们收回了Linux内核社区免费使用BitKeeper的权力。这就迫使Linux开源社区(特别是Linux的缔造者LinusTorvalds)基于使用BitKeeper时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干目标:

速度简单的设计对非线性开发模式的强力支持(允许成千上万个并行开发的分支)完全分布式有能力高效管理类似Linux内核一样的超大规模项目(速度和数据量)

自诞生于2005年以来,Git日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。

6.4 Git的安装

yum installgit# CentOs版本 $ git --version # 查看git的当前版本git version 1.8.3.1 

6.5 在Gitee上面创建项目

这个部分比较长,全部展开来讲太冗余了,毕竟已经写过对应的博客了,而且那里更为详细!因此,本文这里就不再赘述了,详见上面挂着的链接,uu们根据自己的实际需要自行前往。

6.6 三板斧(add / commit / push)

大家之前用过“小乌龟”——TortoiseGit——往gitee上面上传过代码——

在这里插入图片描述

6.6.1 git add

将代码放到刚才下载好的目录中——

gitadd[文件名]
将需要用git管理的文件告知git。

6.6.2 git commit

提交改动到本地——

git commit -m "XXX"

最后的".”表示当前目录。

提交的时候应该注明提交日志,描述改动的详细内容。

6.2.3 git push

同步到远端服务器上。

需要填入用户名密码。同步成功后,刷新Gitee页面就能看到代码改动了。

6.2.4 配置免密码提交

链接:git本地免密码和账号pull、push

6.2.5 其它

git log/status/pull
.ignore
首次使用问题,需要现场看
在这里插入图片描述

7 ~> 调试器 - gdb / cgdb使用

7.1 样例展示:什么样的程序才能调试?

在这里插入图片描述

7.1.1 代码演示

样例代码如下所示——

1#include<stdio.h>23 int Sum(int s,int e)4{5 int result =0;6 int i = s;7 for(;i <= e;i++)8{9 result += i;10}1112return result;13}1415 int main()16{17 int start =1;18 int end =100;19 printf("I will begin\n");20 int n = Sum(start,end);21 printf("running done,result is:[%d-%d]=%d\n",start,end,n);2223return0;24}
在这里插入图片描述

7.1.2 代码运行

[Alice@VM-4-17-centos mycmd]$ vim Makefile [Alice@VM-4-17-centos mycmd]$ make gcc -o cmd.exe mycmd.c [Alice@VM-4-17-centos mycmd]$ ./cmd.exe I will begin running done,result is:[1-100]=5050

7.1.3 什么样的程序才能调试——一个既定事实

在这里插入图片描述

再看一下其它的描述——

在这里插入图片描述

7.2 准备阶段:加上 -g 选项进入debug模式

7.2.1 回顾与新工具概念导入

我们已经熟悉了不少Linux基础开发工具了,像apt / yum,,vim,gcc / g++,make / makefile,git,以及我们今天在这篇博客要介绍并且解决的工具——调试工具:gdb / cgdb

7.2.2 程序的两种发布方式

程序的发布方式有两种:debug 模式和 release 模式,Linux gcc / g++ 出来的二进制程序,默认是 release 模式。

在这里插入图片描述

7.2.3 见一见:调试工具gdb

我们首当其冲就是来见一见gdb——

[Alice@VM-4-17-centos mycmd]$ gdb cmd.exe GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C)2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 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: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/Alice/118/linux-git/mycmd/cmd.exe...(no debugging symbols found)...done. (gdb) quit 

7.2.4 发现:使用gdb调试,必须在源代码生成二进制程序的时候,加上 -g 选项

要使用gdb调试,必须在源代码生成二进制程序的时候,加上 -g 选项,如果没有添加,程序无法被编译。

如下图,描述的就很清楚了——

$ gcc mycmd.c -o mycmd # 默认模式,不⽀持调试 $ file mycmd mycmd: ELF 64-bit LSB shared object, x86-64, version 1(SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=82f5cbaada10a9987d9f325384861a88d278b160, for GNU/Linux 3.2.0, not stripped $ gcc mycmd.c -o mycmd -g # debug模式 $ file mycmd mycmd: ELF 64-bit LSB shared object, x86-64, version 1(SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=3d5a2317809ef86c7827e9199cfefa622e3c187f, for GNU/Linux 3.2.0, with debug_info, not stripped 

7.2.5 演示添加 -g 之后的效果

我们来看一下添加-g之后的效果——

[Alice@VM-4-17-centos mycmd]$ vim Makefile [Alice@VM-4-17-centos mycmd]$ make gcc -o cmd.exe-debug mycmd.c -g [Alice@VM-4-17-centos mycmd]$ ./cmd.exe-debug I will begin running done,result is:[1-100]=5050[Alice@VM-4-17-centos mycmd]$ ll total 32 -rwxrwxr-x 1 Alice Alice 8440 Dec 1 00:49 cmd.exe -rwxrwxr-x 1 Alice Alice 9696 Dec 1 01:07 cmd.exe-debug -rw-rw-r-- 1 Alice Alice 290 Dec 1 01:07 Makefile -rw-rw-r-- 1 Alice Alice 345 Dec 1 00:14 mycmd.c [Alice@VM-4-17-centos mycmd]$ ./cmd.exe I will begin running done,result is:[1-100]=5050[Alice@VM-4-17-centos mycmd]$ ./cmd.exe-debug I will begin running done,result is:[1-100]=5050
在这里插入图片描述

7.3 怎么证明确实存在调试信息呢?

上面我们说 -g 给形成的可执行程序内部添加调试信息,那怎么证明确实存在调试信息呢

我们来看看Linux是怎么读取一个二进制文件的格式的——

7.3.1 readelf -S cmd.exe-debug

[Alice@VM-4-17-centos mycmd]$ readelf -S cmd.exe-debug There are 35 section headers, starting at offset 0x1d20: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 000[1] .interp PROGBITS 0000000000400238 00000238 000000000000001c 0000000000000000 A 001[2] .note.ABI-tag NOTE 0000000000400254 00000254 0000000000000020 0000000000000000 A 004[3] .note.gnu.build-i NOTE 0000000000400274 00000274 0000000000000024 0000000000000000 A 004[4] .gnu.hash GNU_HASH 0000000000400298 00000298 000000000000001c 0000000000000000 A 508[5] .dynsym DYNSYM 00000000004002b8 000002b8 0000000000000078 0000000000000018 A 618[6] .dynstr STRTAB 0000000000400330 00000330 0000000000000044 0000000000000000 A 001[7] .gnu.version VERSYM 0000000000400374 00000374 000000000000000a 0000000000000002 A 502[8] .gnu.version_r VERNEED 0000000000400380 00000380 0000000000000020 0000000000000000 A 618[9] .rela.dyn RELA 00000000004003a0 000003a0 0000000000000018 0000000000000018 A 508[10] .rela.plt RELA 00000000004003b8 000003b8 0000000000000060 0000000000000018 AI 5238[11] .init PROGBITS 0000000000400418 00000418 000000000000001a 0000000000000000 AX 004[12] .plt PROGBITS 0000000000400440 00000440 0000000000000050 0000000000000010 AX 0016[13] .text PROGBITS 0000000000400490 00000490 00000000000001e2 0000000000000000 AX 0016[14] .fini PROGBITS 0000000000400674 00000674 0000000000000009 0000000000000000 AX 004[15] .rodata PROGBITS 0000000000400680 00000680 0000000000000045 0000000000000000 A 008[16] .eh_frame_hdr PROGBITS 00000000004006c8 000006c8 000000000000003c 0000000000000000 A 004[17] .eh_frame PROGBITS 0000000000400708 00000708 0000000000000114 0000000000000000 A 008[18] .init_array INIT_ARRAY 0000000000600e10 00000e10 0000000000000008 0000000000000008 WA 008[19] .fini_array FINI_ARRAY 0000000000600e18 00000e18 0000000000000008 0000000000000008 WA 008[20] .jcr PROGBITS 0000000000600e20 00000e20 0000000000000008 0000000000000000 WA 008[21] .dynamic DYNAMIC 0000000000600e28 00000e28 00000000000001d0 0000000000000010 WA 608[22] .got PROGBITS 0000000000600ff8 00000ff8 0000000000000008 0000000000000008 WA 008[23] .got.plt PROGBITS 0000000000601000 00001000 0000000000000038 0000000000000008 WA 008[24] .data PROGBITS 0000000000601038 00001038 0000000000000004 0000000000000000 WA 001[25] .bss NOBITS 000000000060103c 0000103c 0000000000000004 0000000000000000 WA 001[26] .comment PROGBITS 0000000000000000 0000103c 000000000000002d 0000000000000001 MS 001[27] .debug_aranges PROGBITS 0000000000000000 00001069 0000000000000030 0000000000000000 001[28] .debug_info PROGBITS 0000000000000000 00001099 000000000000010e 0000000000000000 001[29] .debug_abbrev PROGBITS 0000000000000000 000011a7 000000000000008b 0000000000000000 001[30] .debug_line PROGBITS 0000000000000000 00001232 0000000000000059 0000000000000000 001[31] .debug_str PROGBITS 0000000000000000 0000128b 00000000000000d1 0000000000000001 MS 001[32] .symtab SYMTAB 0000000000000000 00001360 0000000000000690 0000000000000018 33518[33] .strtab STRTAB 0000000000000000 000019f0 00000000000001e2 0000000000000000 001[34] .shstrtab STRTAB 0000000000000000 00001bd2 0000000000000148 0000000000000000 001 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), l (large), p (processor specific)

7.3.2 readelf -S cmd.exe-debug | grep -i debug

[Alice@VM-4-17-centos mycmd]$ readelf -S cmd.exe-debug |grep -i debug [27] .debug_aranges PROGBITS 0000000000000000 00001069 [28] .debug_info PROGBITS 0000000000000000 00001099 [29] .debug_abbrev PROGBITS 0000000000000000 000011a7 [30] .debug_line PROGBITS 0000000000000000 00001232 [31] .debug_str PROGBITS 0000000000000000 0000128b 

7.4 常见指令使用(表格形式呈现):调试命令速查表

开始:gdb binFile

退出:Ctrl + d 或 quit调试命令
命令作用样例
代码查看命令
list/l显示源代码,从上次位置开始,每次列出10行list/l 10
list/l 函数名列出指定函数的源代码list/l main
list/l 文件名:行号列出指定文件的源代码list/l mycmd.c:1
程序执行控制
r/run从程序开始连续执行run
n/next单步执行,不进入函数内部(逐过程 F10)next
s/step单步执行,进入函数内部(逐语句 F11)step
continue/c从当前位置开始连续执行程序continue
finish执行到当前函数返回,然后停止finish
until X行号执行到指定行号until 20
断点管理
break/b [文件名:]行号在指定行号设置断点break 10
break/b 函数名在函数开头设置断点break test.c:10
info break/b查看当前所有断点的信息info break
delete/d breakpoints删除所有断点delete breakpoints
delete/d breakpoints n删除序号为n的断点delete breakpoints 1
disable breakpoints禁用所有断点disable breakpoints
enable breakpoints启用所有断点enable breakpoints
info/i breakpoints查看当前设置的断点列表info breakpoints
变量操作
print/p 表达式打印表达式的值print start+end
p 变量打印指定变量的值p x
set var 变量=值修改变量的值set var i=10
display 变量名跟踪显示指定变量的值(每次停止时)display x
undisplay 编号取消对指定编号的变量的跟踪显示undisplay 1
堆栈和局部变量
backtrace/bt查看当前执行栈的各级函数调用及参数backtrace
info/i locals查看当前栈帧的局部变量值info locals
其他命令
quit退出GDB调试器quit

7.5 cgdb(半图形化界面)

前面的gdb虽然是调试,但是是黑屏,不是那么方便。

这时候就要用到cgdb——半图形化界面——一半代码一半调试信息。

7.5.1 安装cgdb

上面的基本调试还是麻烦,虽然是黑屏,但是还是想看到代码调试(半图形化界面)。

艾莉丝推荐uu们安装cgdb:

Centos版本:

sudo yum install -y cgdb 

Ubuntu版本:

sudoapt-getinstall -y cgdb 

7.5.2 下载演示

在这里插入图片描述

7.6 断点

7.6.1 断点的本质

在这里插入图片描述

7.6.2 gdb的使用

(gdb) list(l):查看代码,如(gdb) l 0等等,简写成l。
不用花太多时间在l这个命令上面——cgdb有可视化界面(直接看就可以了)。

(gdb) r:即run,运行。

(gdb) b [文件名.后缀名]:[行号] / (gdb) b 21:b + 行号,在21行打一个断点。

(gdb):用指令查看

在这里插入图片描述

我们都演示一下——

[Alice@VM-4-17-centos linux-git]$ ll total 36-rwxrwxr-x 1 Alice Alice 9688 Dec 112:35 cmd.exe drwxrwxr-x 2 Alice Alice 4096 Nov 3018:03 Jindutiao-2-rw-rw-r--1 Alice Alice 68 Dec 112:35 Makefile drwxrwxr-x 2 Alice Alice 4096 Dec 105:14 mycmd -rw-rw-r--1 Alice Alice 345 Dec 111:57 mycmd.c -rw-rw-r--1 Alice Alice 848 Nov 3017:41 README.en.md -rw-rw-r--1 Alice Alice 937 Nov 3017:41 README.md [Alice@VM-4-17-centos linux-git]$ gdb cmd.exe GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C)2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 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:<http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/Alice/118/linux-git/cmd.exe...done.(gdb) l 8{9 result += i;10}1112return result;13}1415 int main()16{17 int start =1;(gdb)18 int end =100;19printf("I will begin\n");20 int n =Sum(start,end);21printf("running done,result is:[%d-%d]=%d\n",start,end,n);2223return0;24}(gdb) l 01 #include<stdio.h>23 int Sum(int s,int e)4{5 int result =0;6 int i = s;7for(;i <= e;i++)8{9 result += i;10}(gdb) l 11 #include<stdio.h>23 int Sum(int s,int e)4{5 int result =0;6 int i = s;7for(;i <= e;i++)8{9 result += i;10}(gdb) r Starting program:/home/Alice/118/linux-git/cmd.exe I will begin running done,result is:[1-100]=5050[Inferior 1(process 32157) exited normally] Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64 (gdb) l 01 #include<stdio.h>23 int Sum(int s,int e)4{5 int result =0;6 int i = s;7for(;i <= e;i++)8{9 result += i;10}(gdb)1112return result;13}1415 int main()16{17 int start =1;18 int end =100;19printf("I will begin\n");20 int n =Sum(start,end);(gdb)21printf("running done,result is:[%d-%d]=%d\n",start,end,n);2223return0;24}(gdb) b 20 Breakpoint 1 at 0x4005cd: file mycmd.c, line 20.(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005cdin main at mycmd.c:20(gdb) r Starting program:/home/Alice/118/linux-git/cmd.exe I will begin Breakpoint 1, main () at mycmd.c:2020 int n =Sum(start,end);(gdb) s Sum (s=1, e=100) at mycmd.c:55 int result =0;(gdb) n 6 int i = s;(gdb) n 7for(;i <= e;i++)(gdb) n 9 result += i;(gdb)7for(;i <= e;i++)(gdb)9 result += i;(gdb)7for(;i <= e;i++)(gdb) p result $1=3(gdb) p &result $2=(int *)0x7fffffffe40c(gdb) n 9 result += i;(gdb) n 7for(;i <= e;i++)(gdb) n 9 result += i;(gdb) display result 1: result =6(gdb)(gdb)(gdb)(gdb)(gdb)(gdb) n 7for(;i <= e;i++)1: result =10(gdb) n 9 result += i;1: result =10(gdb) n 7for(;i <= e;i++)1: result =15(gdb) n 9 result += i;1: result =15(gdb) n 7for(;i <= e;i++)1: result =21(gdb) n 9 result += i;1: result =21(gdb) n 7for(;i <= e;i++)1: result =28(gdb)9 result += i;1: result =28(gdb)7for(;i <= e;i++)1: result =36(gdb)9 result += i;1: result =36(gdb)7for(;i <= e;i++)1: result =45(gdb)9 result += i;1: result =45(gdb)7for(;i <= e;i++)1: result =55(gdb)9 result += i;1: result =55(gdb)7for(;i <= e;i++)1: result =66(gdb)9 result += i;1: result =66(gdb)7for(;i <= e;i++)1: result =78(gdb)9 result += i;1: result =78(gdb) quit A debugging session is active. Inferior 1[process 32288] will be killed. Quit anyway?(y or n) y 

7.6.3 cgdb的使用

在这里插入图片描述


在这里插入图片描述

7.6.4 打断点和删除断点

Linux操作系统下,打断点和删除断点——

[Alice@VM-4-17-centos linux-git]$ gdb ./process_bar GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C)2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 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:<http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/Alice/118/linux-git/process_bar...(no debugging symbols found)...done.(gdb) l No symbol table is loaded. Use the "file" command.(gdb) list No symbol table is loaded. Use the "file" command.(gdb) r Starting program:/home/Alice/118/linux-git/./process_bar I will begin running done,result is:[1-100]=5050[Inferior 1(process 12969) exited normally] Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.3.x86_64 (gdb) b No default breakpoint address now.(gdb) b mycmd.c:20 No symbol table is loaded. Use the "file" command. Make breakpoint pending on future shared library load?(y or [n]) y Breakpoint 1(mycmd.c:20) pending.(gdb) b 21 No symbol table is loaded. Use the "file" command.(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y <PENDING> mycmd.c:20(gdb) b 21 No symbol table is loaded. Use the "file" command.(gdb) breakpoint 21 Undefined command:"breakpoint". Try "help".(gdb) d 1(gdb) info b No breakpoints or watchpoints.(gdb) quit 

Windows操作系统下,打断点和删除断点——

在这里插入图片描述


再按一次F9或者点一下左侧边界就能删除断点了,但这个操作我们不推荐。

7.6.5 直接删除断点不是一个很好的选择

因为断点体现了调试的痕迹,出现类似的问题方便复现。那么,我们怎么做比较好呢?

直接删除断点不是一个很好的习惯,既然如此,我们就禁用断点——因为 断点是可以“使能”的——enable(打开)或者disable(关闭)的,也就是说,可以启用断点也可以禁用断点。因此,我们就禁用断点——不删,只是这个断点不起作用了——需要时再打开。

在这里插入图片描述
在这里插入图片描述

7.6.6 “使能”的操作

Linux中就是前面介绍的断点是可以 “使能” 的——

禁用第三个断点——

(gdb) disable 3

要启用第三个断点——

(gdb)enable3

7.6.7 深刻理解调试是在干什么

在这里插入图片描述

7.6.8 在一个测试周期,断点编号是线性连续的

什么意思?简而言之,run程序之后,新建1、2、3三个断点,如果删掉了第三个断点,再新建断点的时候,断点编号不会再从3开始,而是从4开始——前提是在一个测试周期内!如果退出调试,再进入,编号也就又重新计算啦。

(gdb) b 21 Breakpoint 2 at 0x4005df: file mycmd.c, line 21. (gdb) b 18 Breakpoint 3 at 0x4005bc: file mycmd.c, line 18. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005a8 in Sum at mycmd.c:12 2 breakpoint keep y 0x00000000004005df in main at mycmd.c:21 3 breakpoint keep y 0x00000000004005bc in main at mycmd.c:18 (gdb) d 3(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005a8 in Sum at mycmd.c:12 2 breakpoint keep y 0x00000000004005df in main at mycmd.c:21 (gdb) b 19 Breakpoint 4 at 0x4005c3: file mycmd.c, line 19. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004005a8 in Sum at mycmd.c:12 2 breakpoint keep y 0x00000000004005df in main at mycmd.c:21 4 breakpoint keep y 0x00000000004005c3 in main at mycmd.c:19 

如下图所示——

在这里插入图片描述

7.6.9 小细节:鼠标不小心滚动之后不在gdb区域了,怎么办?

在这里插入图片描述

这样就可以退回到gdb屏幕了——

在这里插入图片描述

7.6.10 调试命令小合集

b(breakpoint):打断点。

“使能”——

enable:使用某个断点

disable:禁用某个断点

c(continue):从一个断点运行到下一个断点,如果是最后一个断点,就运行到程序结束。

n、s:小范围进行找问题——即小范围精确(先用断点 b 划分大范围)——

s(step):逐语句(相当于F11)——能够调试得足够细,是单步调试的一种,可以进入函数内部。

n(next):逐过程(相当于F10)——单步执行,不进入函数内部,把函数当成一个语句(或者说命令)来执行。

p(print):打印,用来查看函数结果、变量的值。

在这里插入图片描述

上面这些命令使用时我们并没有让程序“跑(run)”起来(打断点、常显示)。

我们可以边调试边打断点(情形:陷入循环,想要跳出)

(gdb)b 12 --> c(跳出) 

until:直接跳转到(超范围了默认就是跑完函数了)

在这里插入图片描述


finish:执行当前函数返回并停止(把该函数执行完)。

在这里插入图片描述

VS其实会有一些功能上的重叠(也不能算是冗余),比如说 [监视] 和 [局部变量] ,局部变量我们用 [局部变量] 查看会更方便一点。

在这里插入图片描述


在这里插入图片描述

bt(backtrace):查看当前函数的调用栈(先进后出后进先出)。

info local:查看局部变量(类似于Windows中的 [局部变量]

7.6.11 查看变量

我们可以查看变量——

**查看变量**


这里注意一个小细节,“取消常显示”的操作和断点的新建、删除很类似——常显示也是有1、2、3……这样的编号的,所以也要通过编号来取消!那么,大胆假设、小心求证——取消常显示再新建常显示也是同理,和断点编号一样也是线性的。

在这里插入图片描述

经过验证,发现结果和我们的猜想吻合,说明事实的确如此——取消常显示再新建常显示也是同理,和断点编号一样也是线性的。

7.6.12 单步调试

n、s:小范围进行找问题(先用断点 b 划分大范围)——

在这里插入图片描述

7.6.13 大范围查找和小范围精确

在这里插入图片描述

7.7 三种常见的技巧 - 加餐环节

对比上面的命令,其实下面的命令还是更有价值一点。

7.7.1 监视变量变化:watch

执行时监视一个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发生变化,GDB会暂停程序的执行,并通知使用者

(gdb) l main 1112return result;13}1415 int main()16{17 int start =1;18 int end =100;19 printf("I will begin\n");20 int n = Sum(start, end);(gdb) b 20 Breakpoint 1 at 0x11c3: file mycmd.c, line 20. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000000011c3 in main at mycmd.c:20 (gdb) r Starting program: /home/whb/test/test/mycmd I will begin Breakpoint 1, main () at mycmd.c:20 20 int n = Sum(start, end);(gdb) s Sum (s=32767, e=-7136) at mycmd.c:5 5{(gdb) n 6 int result =0;(gdb)watch result Hardware watchpoint 2: result (gdb) c Continuing. Hardware watchpoint 2: result Old value = -6896 New value =0 Sum (s=1, e=100) at mycmd.c:7 7 for(int i = s; i <= e; i++)(gdb) c Continuing. Hardware watchpoint 2: result Old value =0 New value =1 Sum (s=1, e=100) at mycmd.c:7 7 for(int i = s; i <= e; i++)(gdb) c Continuing. Hardware watchpoint 2: result Old value =1 New value =3 Sum (s=1, e=100) at mycmd.c:7 7 for(int i = s; i <= e; i++)(gdb) c Continuing. Hardware watchpoint 2: result Old value =3 New value =6 Sum (s=1, e=100) at mycmd.c:7 7 for(int i = s; i <= e; i++)(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20 breakpoint already hit 1time2 hw watchpoint keep y result breakpoint already hit 4times(gdb) d 2(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20 breakpoint already hit 1time(gdb) finish Run till exit from #0 Sum (s=1, e=100) at mycmd.c:7 0x00005555555551d2 in main () at mycmd.c:20 20 int n = Sum(start, end); Value returned is $1=5050
在这里插入图片描述

因此,watch常用于监视指针

7.7.2 确定问题原因并且验证原因:set var

set var:可以直接在调试期间修改变量

更改一下标志位(比如flag,+1 / -1这种),假设我们想得到+-result

我们举个例子,比如set var

// mycmd.c#include<stdio.h>int flag =0;// 故意错误 //int flag = -1; //int flag = 1;intSum(int s,int e){int result =0;for(int i = s; i <= e; i++){ result += i;}return result*flag;}intmain(){int start =1;int end =100;printf("I will begin\n");int n =Sum(start, end);printf("running done, result is: [%d-%d]=%d\n", start, end, n);return0;}
(gdb) l main 1516return result*flag;17}1819 int main()20{21 int start =1;22 int end =100;23 printf("I will begin\n");24 int n = Sum(start, end);(gdb) b 24 Breakpoint 1 at 0x11ca: file mycmd.c, line 24. (gdb) r Starting program: /home/whb/test/test/mycmd I will begin Breakpoint 1, main () at mycmd.c:24 24 int n = Sum(start, end);(gdb) n 25 printf("running done, result is: [%d-%d]=%d\n", start, end, n);(gdb) n running done, result is: [1-100]=0# 这⾥结果为什么是0?26return0;(gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/whb/test/test/mycmd I will begin Breakpoint 1, main () at mycmd.c:24 24 int n = Sum(start, end);(gdb) s Sum (s=32767, e=-7136) at mycmd.c:9 9{(gdb) n 10 int result =0;(gdb) n 11 for(int i = s; i <= e; i++)(gdb)13 result += i;(gdb)11 for(int i = s; i <= e; i++)(gdb)13 result += i;(gdb)until14 Sum (s=1, e=100) at mycmd.c:16 16return result*flag;(gdb) p result $1=5050(gdb) p flag $2=0(gdb)set var flag=1# 更改flag的值,确认是否是它的原因(gdb) p flag $3=1(gdb) n 17}(gdb) n main () at mycmd.c:25 25 printf("running done, result is: [%d-%d]=%d\n", start, end, n);(gdb) n running done, result is: [1-100]=5050# 是它的原因26return0;

7.7.3 条件断点(也是断点)

条件断点的类型和普通断点一样,也是breakpoint,多了个条件——“stop only . . .([条件])”

7.7.3.1 添加条件断点
(gdb) l main 1112return result;13}1415 int main()16{17 int start =1;18 int end =100;19 printf("I will begin\n");20 int n = Sum(start, end);(gdb) b 20 Breakpoint 1 at 0x11c3: file mycmd.c, line 20. (gdb) r Starting program: /home/whb/test/test/mycmd I will begin Breakpoint 1, main () at mycmd.c:20 20 int n = Sum(start, end);(gdb) s Sum (s=32767, e=-7136) at mycmd.c:5 5{(gdb) n 6 int result =0;(gdb) n 7 for(int i = s; i <= e; i++)(gdb) n 9 result += i;(gdb) display i 1: i =1(gdb) n 7 for(int i = s; i <= e; i++)1: i =1(gdb) n 9 result += i;1: i =2(gdb) n 7 for(int i = s; i <= e; i++)1: i =2(gdb) n 9 result += i;1: i =3(gdb)7 for(int i = s; i <= e; i++)1: i =3(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20 breakpoint already hit 1time(gdb) b 9if i ==30# 9是⾏号,表⽰新增断点的位置 Breakpoint 2 at 0x555555555186: file mycmd.c, line 9. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20 breakpoint already hit 1time2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9 stop only if i ==30(gdb) finish Run till exit from #0 Sum (s=1, e=100) at mycmd.c:7 Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9 9 result += i;1: i =30(gdb) finish Run till exit from #0 Sum (s=1, e=100) at mycmd.c:9 0x00005555555551d2 in main () at mycmd.c:20 20 int n = Sum(start, end); Value returned is $1=5050
7.7.3.2 给已经存在的断点新增条件
(gdb) l main 1112return result;13}1415 int main()16{17 int start =1;18 int end =100;19 printf("I will begin\n");20 int n = Sum(start, end);(gdb) b 20 Breakpoint 1 at 0x11c3: file mycmd.c, line 20. (gdb) r Starting program: /home/whb/test/test/mycmd I will begin Breakpoint 1, main () at mycmd.c:20 20 int n = Sum(start, end);(gdb) s Sum (s=32767, e=-7136) at mycmd.c:5 5{(gdb) n 6 int result =0;(gdb) n 7 for(int i = s; i <= e; i++)(gdb) n 9 result += i;(gdb)7 for(int i = s; i <= e; i++)(gdb)9 result += i;(gdb)7 for(int i = s; i <= e; i++)(gdb)9 result += i;(gdb)7 for(int i = s; i <= e; i++)(gdb) b 9# 我们在第9⾏新增⼀个断点,⽤来开始测试 Breakpoint 2 at 0x555555555186: file mycmd.c, line 9. (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20 breakpoint already hit 1time2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9 (gdb) n Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9 9 result += i;(gdb) n 7 for(int i = s; i <= e; i++)(gdb) n Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9 9 result += i;(gdb) condition 2i==30#给2号断点,新增条件i==30(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20 breakpoint already hit 1time2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9 stop only ifi==30 breakpoint already hit 2times(gdb) n 7 for(int i = s; i <= e; i++)(gdb) n 9 result += i;(gdb) c Continuing. Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9 9 result += i;(gdb) p i $1=30(gdb) p result $2=435
7.7.3.3 注意

条件断点添加常见两种方式:1、新增;2、给已有断点追加(注意两者的语法有区别,不要写错了!),

在这里插入图片描述

新增:b行号 / 文件名——

行号 / 函数名 if i ==30(条件)

给已有断点追加条件:condition 2 i == 30,其中2是已有断点编号,没有if。

cgbd分屏操作ESC进入代码屏,按 i 回到gdb屏


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!

往期回顾:

【Linux基础开发工具 (六)】Linux中的第一个系统程序——进度条Linux:详解回车、换行与缓冲区

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡૮₍ ˶ ˊ ᴥ ˋ˶₎ა

Read more

Flutter 组件 conventional 适配鸿蒙 HarmonyOS 实战:约定式提交标准,构建自动化版本治理与 CI/CD 质量治理架构

Flutter 组件 conventional 适配鸿蒙 HarmonyOS 实战:约定式提交标准,构建自动化版本治理与 CI/CD 质量治理架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 conventional 适配鸿蒙 HarmonyOS 实战:约定式提交标准,构建自动化版本治理与 CI/CD 质量治理架构 前言 在鸿蒙(OpenHarmony)生态迈向大规模研发协同、涉及数十个跨职能团队共同维护大型 HAP/HSP 项目的背景下,如何确保每一行代码的变更都“有迹可循”、在端侧实现自动化的版本语义化(Semantic Versioning)管理,已成为衡量工程化成熟度的“地基”。在鸿蒙设备这类强调分布式协同与持续集成(CI)交付的环境下,如果代码提交记录(Commit Messages)依然采用随意的口语化描述,由于由于缺乏机器可读性,极易由于由于无法自动生成变更日志(Changelog)导致跨版本维护时的回溯成本激增。 我们需要一种能够强制执行规范检查、支持 RFC 标准且具备解析语义结构的提交治理框架。 conventional 为 Flutter

By Ne0inhk
Spring Boot/Spring MVC核心注解深度解析

Spring Boot/Spring MVC核心注解深度解析

—知识点专栏— 本文将对Spring Boot和Spring MVC框架中最核心、最高频使用的15个注解进行深度剖析。我们将从请求路由映射(@RequestMapping系列)入手,详细讲解数据绑定、参数传递(@RequestBody, @RequestParam等)的机制,进而探讨RESTful架构中的控制器(@RestController)和组件管理(@Service, @Autowired)的精髓。通过丰富的代码示例和图表,帮助开发者全面掌握这些注解,并迅速提升Spring应用的开发效率和代码质量。 📌 目录 * 一、Spring/Spring MVC注解的核心作用 * 二、请求映射与RESTful API注解系列 * 2.1. @RequestMapping: 路由映射的基石 * 2.2. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping: HTTP方法快捷注解 * 2.3. @RestController 与 @Controller 的区别 * 三、请求参数绑定与数据处理注解

By Ne0inhk
【OpenClaw从入门到精通】第03篇:吃透Gateway/Skills/ClawHub核心概念(2026实测+避坑)

【OpenClaw从入门到精通】第03篇:吃透Gateway/Skills/ClawHub核心概念(2026实测+避坑)

摘要:本文针对OpenClaw新手易混淆的核心概念痛点,以通俗类比+实操演示拆解OpenClaw核心、Gateway、Skills、ClawHub四大组件。通过“数字员工团队”类比明确各组件定位:OpenClaw核心是“老板”(调度中心)、Gateway是“前台+后勤”(后台进程)、Skills是“专业员工”(功能插件)、ClawHub是“人才市场”(技能商店)。补充版本更名史、技能加载优先级、ClawHub与GitHub区别等关键细节,结合“AI融资新闻查询并邮件推送”虚拟案例演示组件协同流程,梳理5个高频认知误区及解决方案。所有内容基于2026年官方文档实测,案例为虚拟构建,代码仅作示例未上传GitHub,兼顾新手理解与进阶实操参考,帮助读者建立清晰的OpenClaw架构认知。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】

By Ne0inhk