在之前的Linux《基础开发工具》上和中当中我们已经了解了一些的Linux当中的基础开发工具,接下来在本篇当中我们将继续来了解两个基本的开发工具git和gbd,信息通过本篇的学习让你了解和这两个工具的基本使用方法,接下来就开始本篇的学习吧!!!
1.版本控制器Git
1.1 版本控制器的作用
在之前你大概率有过这样的经历:在编写各种文档时,为了防止文档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出一个副本,比如:
“报告-v1”
“报告-v2”
“报告-v3”
“报告-确定版”
“报告-最终版”
“报告-究极进化版”
...
每个版本有各自的内容,但最终会只有⼀份报告需要被我们使用。
每个版本有各自的内容,但最终会只有⼀份报告需要被我们使用 。
但在此之前的工作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的文件就越来越
多,文件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各自都是修改了什么
吗?
文档如此,我们写的项目代码,也是存在这个问题的!!
为了能够更方便我们管理这些不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让你了解到⼀个文件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录工程的每⼀次改动和版本迭代的⼀个管理系统,同时也方便多人协同作业。
一开始的版本管理器是将对应的历史创建的各个版本的软件或者报告等存储在本地当中,但是这种方式就无法实现多人开发的进行,每个开发者都只能在自己的本地当中进行版本的控制,因此在此之后就诞生了在远端的服务器当中进行版本的控制,这样就可以使得各个开发者都可以将开发过程中项目的各个版本同步到服务器上,这就解决了开发者之间无法实现协同开发的问题。
在此所有开发者只需要将在本地的仓库同步到远端的仓库就可以在远端的仓库当中存储所有的版本信息
现在主流的版本控制器就是git,我们使用的gitee、github等都是基于git的网站或者平台
Git 可以控制电脑上所有格式的⽂件,例如 doc、excel、dwg、
dgn、rvt等等。对于我们开发⼈员来说,Git 最重要的就是可以帮助我们管理软件开发项目中的源代码文件!有了git我们就不再害怕在本地的电脑出现问题时会造成代码丢失的问题,在此我们只需要在进行开发时将代码同步到远端的gitee或者githu上就可以在本地的代码丢失时将远端的数据拉到本地即可。
1.2 git简史
在了解git之前我们要先来了解git大概的的发展历史,这有助于我们更好的了解git
首先要了解的是git也是与Linux一样也是开源的。
在Linux诞生之后由于Linux的作者托瓦兹将Linux开源之后,世界各地的参与Linux项目的人越来越多了,在此过程当中托瓦兹需要将世界上的工程师提交的代码进行审核,若对应的代码符合要求就将其上线到Linux当中,但是由于参与Linux项目的人太多了,提交的代码也越来越多,托瓦兹一个人已经无法将所有的代码进行审核。此时托瓦兹就想能不能使用一个软件将所有提交的代码进行管理,之后再将这些代码让Linux的开发工程师进行审核等操作。在此托瓦兹找寻找程过程中寻找的是免费的版本控制器,这是因为托瓦兹认为Linux是开源的但如果版本控制器是收费的这就和Linux的开源精神相违背了。之后托瓦兹发现进行版本控制的的软件都是收费的,之后一家公司看到Linux开发者无私的精神愿意将自己的版本控制器免费给Linux社区使用,但是在社区使用这款版本控制器的过程中出现了有些人将该软件破解了,之后该版本控制器的公司就不再将该版本控制器免费提供给Linux社区了。
之后托瓦兹在无法得到使用市面上免费的版本控制器之后就自己写了一个开源的版本控制器,这就是以上提到的git
1.3 gitee使用
以上我们初步了解了git的使用以及git的由来,那么接下来我们就来了解一个基于git的网站gitee如何进行使用
在此点击以上的链接就可以打开gitee的官网,接下来会讲解如何在gitee下创建远程的仓库,之后如何将本地的仓库同步到远端的仓库当中
当你创建了账户之后接下来在你的gitee主页当中就可以看到右上角有一个+,点击之后再点击创建仓库
之后就可以在gitee当中进行仓库的创建了,在此仓库的命名由你决定,一般我们会将仓库内存储的数据最主要的特点作为仓库名,之后选择开源还是闭源;开源就是其他人都可以查看你gitee该仓库内的数据,闭源就是仓库内的数据只有你或者指定的人才能查看。
在初始化仓库当中,将语言选择C++,添加.gitignore为C++
注:.gitignore的作用在之后会进行讲解
在选择分支模型当中我们选择单分支即可,在一些大的公司当中需要进行多人协作的开发就可能会使用到其他的生成/开发模型等
创建仓库完成之后就会出现以下的页面,接下来点击其中的克隆/下载
之后对应的复制对应的HTTPS即可
1.4 Linux内git操作
在以上我们了解了如何在gitee当中创建仓库,那么接下来就接着来学习如何在Linux当中使用git将对应的代码拉到远程仓库当中
在Linux当中使用git之前需要先在Linux当中使用yum下载git
sudo yum install git
在使用了以上的命令在Linux当中下载了git之后接下来就可以使用git clone来将以上我们在gitee当中创建的远程仓库同步到本地的Linux当中
git clone [HTTPS地址]
使用了以上的指令之后接下来就可以在当前的目录下看到创建了一个和我们之前创建的仓库同名的目录
进入到该目录之后就可以看到已经将远程仓库当中的数据同步到Linux当中
了解了远端的仓库如何拉到Linux当中之后接下来来了解如何将Linux当中的文件代码传输到远端的仓库当中
在进行传输只需要进行三步即可实现,分别是add、commit、push
首先在当前的linux目录下创建一个名为test.c的文件,之后在该文件内写入以下的内容
在此要进行传输时首先使用add来实现将对应的文件传输到本地的缓冲区当中
在此要查询对应的文件是否进入到缓冲区当中就需要使用git status
git status
以上我们使用了add指令之后其实对应的文件只是被拷贝到缓冲区当中,此时还未被拷贝到本地的git仓库当中
在此可以使用ls -a看到在当中路径下存在一个名为 .git 的隐藏文件,并且在该目录当中还没有我们创建的test.c的文件
要使得在缓冲区当中的文件拷贝到本地的git仓库当中接下来再使用git commit 就可实现
git commit -m "XXX"
在使用git commit要带上-m选项,并且在此之后还要在之后再使用引号写上该文件的简介
完成了以上的操作之后接下来再使用push就可以将本地当前git仓库内的文件同步到远端的仓库当中
git push
接下来在使用该指令之后只需要输入你的gitee的用户名以及gitee账号的密码即可实现文件的传输
此时在gitee就可以看到test.c已经同步到远端的仓库当中
以上我们就了解了在Linux当中如何使用git来将文件同步到远端的仓库当中,那么接下来了解之前提到的.gitignore文件的作用
首先先在当中的目录下一个 test.o的文件,之后再按照以上的add、commit、push三步来实现远端的同步
在以上的操作过程当中就可以看出在使用add时就会没有对应的文件没有将对应的文件传输到缓冲区当中,此时通过该示例就可以了解到.gitignore的作用就是在进行git操作时进行特点文件的忽略,在.gitignore内保存的就是要进行忽略文件的后缀
在一般情况下我们除了在Linux当中进行文件远端的同步外还会进行Linux与Windows的协同开发,那么首先就要了解如何在Windows下将远端的仓库同步到本地。在此确实可以和之前Linux一样使用命令行进行操作,但是在Windows还有更好地方式进行传输,同步等操作,但是使用小乌龟会更加地简便。
详细教程可以观看以下地视频:
gitee(码云)的注册和代码提交【手把手】_哔哩哔哩_bilibili
在此在Windows当中点击pull就可以将远端地仓库同步到本地
接下来在Windows当中将之前我们在Linux当中创建地test.c文件进行修改再加上一行代码
之后进行add、commit、push同步到远端
接下来在Linux当中继续使用创建另外地文件同步到远端
但是此时在使用push就会出现以下地错误
那么此时地问题是什么呢?
其实问题很简单之前在Windows端我们将原来地test.c文件进行了修改,而此时Linux端还是保存的是之前未修改文件的数据,这是就会形成远端仓库和Linux本地仓库的人冲突,此时的冲突就是提醒用户要和远端进行同步了,在此就需要使用 pull来将远端的仓库同步到本地
git pull
以上就是关于git基本的使用,更多的git操作将在之后的git专栏当中进行讲解
2.gdb
通过之前的学习我们知道软件发布的模式有两种分别是debug模式和release模式,一般我们在开发时的模式是debug模式,而最终发布的模式是release模式。
之前在windows当中默认在进行代码的编写时的模式就是debug模式,但是在之前我们在Linnux当中使用vim等编辑器编写完代码之后接下来使用gcc/g++编译默认生成的是release模式下的程序。
我们知道在release模式下是无法进行调试工作的,那么接下来我们就要来学习如何在Linux当中将可执行程序形成为debug模式。
在Linux当中要进行调试就需要使用到gdb,同时还必须在源代码生成二进制程序的时候, 加上 -g 选项,如果没有添加,程序无法被编译。
那么接下来我们实现了进度条项目的代码,此时如果我们要进行调试就需要将之前实现makefile内的依赖方法进行修改;加上-g选项
接下来使用make命令之后就会发现形成的可执行程序相比之前的要大了一些,在此我们还可以通过以下的readelf指令进一步验证
此时就可以看到在形成的可执行程序process.exe内包含了对应调试信息
因此总的来说-g选项的作用就是让最后形成的可执行程序添加调试信息,也就是改为debug模式。
接下来我们来基于以下的代码来学习gdb内相关的指令
#include <stdio.h>
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result*flag;
}
int main()
{
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);
return 0;
}
以上的代码很好理解,其实现的功能就是计算出1到100之间的全部整数之和,接下来我们就依据以上的代码来了解如何使用gdb来进行调试
实现在当前路径下创建对应的makefile文件,内部内容如下所示:
创建的makefile之后接下来使用make命令创建出了对应的mytest可执行程序后再使用gdb mytest指令就会出现以下的信息,此时就表明我们进入到gdb当中了
接下来要查看可执行程序内的代码就需要使用list指令,在此直接使用l也是可以的
以上我们就可以看到可执行程序内的代码了,但是这样在gdb内进行调试是在黑屏下进行的,还是比较难操作的,因此在此推荐的是使用cgdb来进行调试,在Linux当中使用cgdb要先下载cgdb
sudo sudo yum install -y cgdb
有了cgdb之后我们再来对之前的mytest进行调试,使用对应的指令 cgdb mytest,之后就会进入到cgdb当中
此时进行调试时程序的代码在上方,调试的信息在下方,相比之前的gdb现在的cgdb就更加显著了。
在此要显示出代码使用的还是list
list/l | 显示源代码,从上次位置开始,每次列出 10行 |
list/l 函数名 | 列出指定函数的源代码 |
list/l ⽂件名:行号 | 列出指定文件的源代码 |
要运行以上的程序就需要使用到run,可以直接使用r,在没有设置断点时使用之后就会直接将该程序跑完。
如果要设置断点就需要使用到b,在此b的使用有以下的形式
b [文件件名:]行号 | 在指定行号设置断点 |
b 函数名 | 在函数开头设置断点 |
b 行号 | 在指定行号设置断点 |
那么再设置了断点之后要查看所有的断点呢?那么此时就需要使用到info
info b | 查看当前所有断点的信息 |
只需要使用info b指令就可以查看当前设置的所有断点的信息
在此以上就是使用info b之后显示的结果,在此Num表示的断点编号 。
那么要将创建的断点进行删除又要怎么操作呢?在此就需要使用到d,在此要删除对应的断点不能使用行号来进行删除,而是需要使用对应的断点编号来删除
d n | 删除序号为n的断点 |
以上我们将断点1删除之后再在19行创建断点就会发现断点编号变为2了,这是因为在gdb当中不退出断点编号会依次递增
在之前VS当中当我们设置了断点之后接下来F5程序就会跑到断点处就停止,接下来我们就可以使用F10或者F11,F10为逐过程,F11为逐语句。在gdb当中也是可以进行这两个操作的。需要使用到以下的指令。
n/next | 单步执行,不进入函数内部 |
s/step | 单步执行,进入函数内部 |
以上我们在程序的19行打了断点,接下来使用r就跑到19行时就停止了,接下来要进入到函数内就使用s ,要直接执行Sum函数就使用n。
通过以上就可以看出当gdb是会自动记录最新的一条指令,这样在使用s/n时就不需要一直输入再点击回车,只需要第一次输入之后接下来点击回车即可。
并且当要结束这一次的调试时只需要输入r再输入y就可以重新开始调试
在调试当中当我们进入到函数当中时要结束该函数的调试,直接运行到函数的返回处就需要使用到以下的指令
finish | 执行到当前函数返回,然后停止 |
例如以上的程序当中,当我们使用s进入到Sum函数之后接下来如果要快速的使得该函数运行完就可以使用finish来实现,此时就会运行到程序的19行结束
在调试过程当中要查看指定变量的值就需要使用到以下的指令
p 变量 | 打印指定变量的值 |
例如在以上我们在调试当中运行完Sum函数之后,此时查看变量n的值就会发现此时的值是随机值,这是因为当前还未将Sum的返回值赋值给n
只需要再执行一条语句再查看n的值就变为了5050
在gdb当中如果当前有多个断点但是有的断点我们现在不想使用,但是又不想删除此时就需要使用到以下的指令,在此该指令就能实现断点使能
disable 断点编号 | 禁用对应编号的断点 |
例如在以上的程序当中我们使用q退出cgdb之后重新进入再在16行创建一个断点
此时就可以看到创建断点时默认的Enb是y的,也就是创建断点之后默认是开启的,那么接下来将断点1 使用disable之后再进行r之后就会使得程序运行到断点2处停止
那么要将被禁用的断点再重新开启要怎么操作呢?在此就要使用到以下的指令
enable 断点编号 | 启用对应编号的断点 |
以上我们就了解了基本的调试当中的基本操作,接下来我们就要思考调试的本质是什么?
通过之前的经验我们知道,在进行调试时一般是我们写的代码出现了问题,那么接下来就进行调试来找出问题,此时打不同的断点其实就是将代码进行块级别的划分,这样就可以以块单位进行快速的定位出现问题的区域。
那么如果当程序运行起来之后要从一个断点跳转至下一个断点,那么就要使用到以下的指令
continue/c | 从当前位置开始连续执行程序 |
之前我们了解的finish指令其实作用是确认问题是否出现在对应的函数内部,那么如果在进入函数之后要在函数内部进行局部区域的快速查找呢?
要进行以上的操作就需要使用到以上下的指令
until X行号 | 执⾏到指定行号 |
例如以下进入到Sum函数内部之后当前在循环内部时要快速的跳出循环就可以使用until
那么使用断点以及finish和until指令就可以实现找出问题,那么接下来找出问题之后就要查看出现问题的上下文代码来找出问题出现的位置
假设将以上的代码修改为以下的形式,在此将Sum函数的返回值乘flag变量,但是flag的值为0,这就会使得最后返回的结果为0,那么接下来假设我们不知道该问题,接下来就要通过调试来找出问题
#include <stdio.h>
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result*flag;
}
int main()
{
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);
return 0;
}
当我们进行调试时进入到Sum函数内部之后,接下来在使用s时我们就需要查看函数内变量的值变化,但是这是使用p指令就不太方便 ,因此接下来就要再来了解一个指令
display 变量名 | 跟踪显示指定变量的值(每次停止时) |
以上使用diaplay之后就可以在使用s的同时显示变量的值
在此要取消对应变量的显示就可以使用以下的指令
undisplay 编号 | 取消对指定编号的变量的跟踪显示 |
注意:在此使用undisplay之后跟的是编号而不是变量的名称
我们之前已经了解过了p指令的使用方法,在此对p指令再进行使用的补充,p之后可以跟表达式,使用之后就会输出该表达式的结果
例如以上的代码当中当我们调试到代码的11行时,也就是Sum函数的结尾时就可以发现此时的result还是我们预期的5050,那么此时就可以使用flag*result的表达式来将函数的返回值提前得到,这样就可以判断出是flag出现问题。
gdb几个使用技巧
了解以上的指令我们就可以正常的使用gdb了,接下来再来了解几个加餐的指令来提高我们代码调试的效率
1.watch
一般在程序当中会有一些变量,那么这变量的值在程序执行的过程当中是不能出现改变的,那么此时就可以使用watch来监视这些量,只有在变量的值出现变化时才会显示
例如在以上的代码当中如果我们使用watch监视resutl,那么就会出现以下的结果
注:如果你有⼀些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如果变化了,就会通知你
2. set var
在之前使用调试的时候当出现问题之后要进行修改都是要先退出调试,之后再进行一次调试来验证修改之后的代码是否符合我们的要求。这就比较繁琐,那么有什么方法可以在调试期间就进行验证的方法呢?
其实是有的,这就是阶而下了我们要学习的set var
例如在以上的代码当中我们就可以使用set var来验证判断是flag出现问题之后再修改flag的值能否让程序正常的运行
3. 条件断点
如果我们想创建一个断点使得程序在满足对应的条件时停止,在gdb当中要如何操作呢?
其实在此是分为两种情况,第一种是当前要创建一个条件断点,那么和之前创建断点类似,只不过在创建之后再加上对应的条件即可
b 行号 if 条件
例如在以上的代码当中要让在第9行且i等于10时候停下就可以使用到条件断点
此外除了以上的情况外,我们还有可能会先创建了一个普通的断点之后要使其变为条件断点,那么这时就需要使用到如下指令
condition 断点编号 新增条件
例如假设我们在以上的代码当中在第9行创建一个普通的断点,那么此时要使得程序运行到i=10的时候停止就需要使用到condition
4. gdb屏与代码屏切换
当我们要查看文件的代码时就可以点击ESC键,这时就可以进入到代码屏,接下来就可以使用上下键进行代码的翻阅
此时要从代码屏退回gdb屏只需要点击i键
以上就是本篇的全部内容了, 在此我们就了解完了Linux当中的所有基本的开发工具,那么接下来我们就将开始进程的学习,未完待续……