【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

git国内版下载以及环境配置

git国内版下载以及环境配置

首先我这里提供国内镜像地址: 你可以通过以下国内镜像地址下载 Git 64 位 Windows 版本: 1. GitCode 镜像:提供了最新版本的 Git 安装包,适用于 Windows 64 位系统。 下载地址:Git-2.42.0.2-64-bit.exe 2. 阿里镜像:CNPM Binaries Mirror 提供了 Git 的多个版本,你可以选择最新版本进行下载。 访问地址:阿里镜像 Git 下载页面 3. Gitee 镜像:Gitee 提供了 Git for Windows 的镜像,不定期更新最新版本。 访问地址:Gitee Git for

By Ne0inhk
【AI大模型前沿】昆仑万维开源Skywork-R1V3:38B多模态推理模型,高考数学142分刷新开源SOTA

【AI大模型前沿】昆仑万维开源Skywork-R1V3:38B多模态推理模型,高考数学142分刷新开源SOTA

系列篇章💥 No.文章1【AI大模型前沿】深度剖析瑞智病理大模型 RuiPath:如何革新癌症病理诊断技术2【AI大模型前沿】清华大学 CLAMP-3:多模态技术引领音乐检索新潮流3【AI大模型前沿】浙大携手阿里推出HealthGPT:医学视觉语言大模型助力智能医疗新突破4【AI大模型前沿】阿里 QwQ-32B:320 亿参数推理大模型,性能比肩 DeepSeek-R1,免费开源5【AI大模型前沿】TRELLIS:微软、清华、中科大联合推出的高质量3D生成模型6【AI大模型前沿】Migician:清华、北大、华科联手打造的多图像定位大模型,一键解决安防监控与自动驾驶难题7【AI大模型前沿】DeepSeek-V3-0324:AI 模型的全面升级与技术突破8【AI大模型前沿】BioMedGPT-R1:清华联合水木分子打造的多模态生物医药大模型,开启智能研发新纪元9【AI大模型前沿】DiffRhythm:西北工业大学打造的10秒铸就完整歌曲的AI歌曲生成模型10【AI大模型前沿】R1-Omni:阿里开源全模态情感识别与强化学习的创新结合11【AI大模型前沿】Qwen2.5-Omni:

By Ne0inhk

Zvec 架构深度解析:阿里巴巴开源的轻量级进程内向量数据库

Zvec 架构深度解析:阿里巴巴开源的轻量级进程内向量数据库 Zvec 是阿里巴巴开源的一个轻量级、闪电般快速的进程内向量数据库。本文将深入分析 Zvec 的代码架构,揭示其核心设计理念和技术实现细节。 一、项目概览 1.1 核心特性 Zvec 基于 Alibaba 久经考验的 Proxima 向量搜索引擎构建,提供生产级的低延迟、可扩展的相似度搜索能力: * 极致性能:毫秒级搜索数十亿级向量 * 简单易用:无需服务器配置,零依赖安装 * 混合向量支持:同时支持稠密向量(Dense)和稀疏向量(Sparse) * 混合搜索:语义相似度 + 结构化过滤 * 随处运行:嵌入到应用进程内运行 1.2 技术栈 组件技术语言C++17构建系统CMakePython绑定Pybind11存储引擎RocksDB向量索引Proxima (IVF, HNSW, Flat)序列化Protobuf压缩LZ4位图CRoaring距离计算SIMD 加速 1.3

By Ne0inhk