【Linux学习笔记】开发工具git和gbd和cgbd的介绍和使用
🔥个人主页:大白的编程日记
🔥专栏:Linux学习笔记
文章目录
前言
哈喽,各位小伙伴大家好!上期我们讲了Makefile,今天我们讲的是git和gbd的介绍和使用。话不多说,我们进入正题!向大厂冲锋!
一. 版本控制器Git
- 关于Git的更详细讲解请移步:Git学习目录
不知道你工作或学习时,有没有遇到这样的情况:我们在编写各种文档时,为了防止文档丢失,更改失误,失误后能恢复到原来的版本,不得不复制出一个副本,比如;
“报告-v1”
“报告-v2”
“报告-v3”
“报告-确定版”
“报告-最终版”
“报告-究极进化版”
…
每个版本有各自的内容,但最终会只有一份报告需要被我们使用。
但在此之前的工作都需要这些不同版本的报告,于是每次都是复制粘贴副本,产出的文件就越来越多,文件多不是问题,问题是:随着版本数量的不断增多,你还记得这些版本各自都是修改了什么吗?
文档如此,我们写的项目代码,也是存在这个问题的!!
1.1版本控制器
- 为了能够更方便我们管理这些不同版本的文件,便有了版本控制器。所谓的版本控制器,就是能让你了解到一个文件的历史,以及它的发展过程的系统。通俗的讲就是一个可以记录工程的每一次改动和版本迭代的一个管理系统,同时也方便多人协同作业。
目前最主流的版本控制器就是Git。Git可以控制电脑上所有格式的文件,例如doc、excel、dwg、dgn、rvt等等。对于我们开发人员来说,Git最重要的就是可以帮助我们管理软件开发项目中的源代码文件!
1.2 git 简史
同生活中的许多伟大事物一样,Git诞生于一个极富纷争大举创新的年代。
Linux内核开源项目有着为数众多的参与者。绝大多数的Linux内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991一2002年间)。到2002年,整个项目组开始启用一个专有的分布式版本控制系统BitKeeper来管理和维护代码。
到了2005年,开发BitKeeper的商业公司同Linux内核开源社区的合作关系结束,他们收回了Linux内核社区免费使用BitKeeper的权力。这就迫使Linux开源社区(特别是Linux的缔造者Linus
Torvalds)基于使用BitKeeper时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干 目标:
- 速度
- 简单的设计
对非线性开发模式的强力支持(允许成千上万个并行开发的分支) - 完全分布式
- 有能力高效管理类似Linux内核一样的超大规模项目(速度和数据量)
自诞生于2005年以来,Git日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。
1.3 安装git
yum install git/apt install git
6-4在Github创建项目
注册账号
这个比较简单,参考着官网提示即可.需要进行邮箱校验
创建项目
- 登陆成功后,进入个人主页,点击左下方的Newrepository按钮新建项目
- 然后跳转到的新页面中输入项目名称(注意,名称不能重复,系统会自动校验,校验过程可能会花费几秒钟).校验完毕后,点击下方的Createrepository按钮确认创建
- 在创建好的项目页面中复制项目的链接,以备接下来进行下载,
下载项目到本地
创建好一个放置代码的目录。
git clone [url]
这里的url就是刚刚建立好的项目的链接.
1.4 三板斧
- git add
将代码放到刚才下载好的目录中
git add [⽂件名]
将需要用git管理的文件告知 git
- git commit
提交改动到本地
git commit -m "XXX"
最后的"."表示当前目录
提交的时候应该注明提交日志,描述改动的详细内容,
- git push
同步到远端服务器上
git push
需要填入用户名密码.同步成功后,刷新Github页面就能看到代码改动了.
配置免密码提交:配置免密码提交
- 其他
-
git log/status/pull
-
ignore
-
首次使用问题,需要现场看
二. 调试器-gdb/cgdb使用
// mycmd.c
#include <stdio.h>
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result;
}
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;
}
7-2预备
- 程序的发布方式有两种,
debug
模式和release
模式,Linuxgcc/g++
出来的二进制程序,默认是release
模式。 - 要使用gdb调试,必须在源代码生成二进制程序的时候,加上
-g
选项,如果没有添加,程序无法被编译
$ gcc mycmd.c - o mycmd - g选项,如果没有添加,程序⽆法被
# 默认模式,不⽀持调试
$ 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
2.1常见使用
开始: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 | 单步执行,不进入函数内部 | next |
s/step | 单步执行,进入函数内部 | step |
break/b [文件名:]行号 | 在指定行号设置断点 | break 10 |
break/b 函数名 | 在函数开头设置断点 | break main |
info break/b | 查看当前所有断点的信息 | info break |
finish | 执行到当前函数返回,然后停止 | finish |
print/p 表达式 | 打印表达式的值 | print start+end |
p 变量 | 打印指定变量的值 | p x |
set var 变量=值 | 修改变量的值 | set var i=10 |
continue/c | 从当前位置开始连续执行程序 | continue |
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 |
display 变量名 | 跟踪显示指定变量的值(每次停止时) | display x |
undisplay 编号 | 取消对指定编号的变量的跟踪显示 | undisplay 1 |
until 行号 | 执行到指定行号 | until 20 |
backtrace/bt | 查看当前执行栈的各级函数调用及参数 | backtrace |
info/i locals | 查看当前栈帧的局部变量值 | info locals |
quit | 退出GDB调试器 | quit |
2.2 常见技巧
2.2.1 watch
执行时监视⼀个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发生变化,GDB会暂停程序的执行,并通知使用者
-
📌 注意:
如果你有一些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如果变化了,就会通知你。
2.2.2 setvar确定问题原因
更改一下标志位,假设我们想得到+ -result
// mycmd.c
#include <stdio.h>
int flag = 0; //
故意错误
//int flag = -1;
//int flag = 1;
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;
}
(gdb) l main
15
16
17
18
19
}
return result*flag;
int main()
20
21
22
23
24
{
int start = 1;
int end = 100;
printf("I will begin\n");
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
26
return 0;
#
这⾥结果为什么是
0
?
(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
(gdb) n
11
(gdb)
13
(gdb)
11
(gdb)
13
int result = 0;
for(int i = s; i <= e; i++)
result += i;
for(int i = s; i <= e; i++)
result += i;
(gdb) until 14
Sum (s=1, e=100) at mycmd.c:16
16
return 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:2
25
printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=5050
26
return 0;
2.2.3 条件断点
添加条件断点
(gdb) l main
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
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
(gdb)n
7
(gdb)n
9
(gdb)
7
(gdb)
9
(gdb)
7
(gdb)
9
(gdb)
7
(gdb)
b 9
int result = 0;
for (int i = s; i <= e; i++)
result += i;
for (int i = s; i <= e; i++)
result += i;
for (int i = s; i <= e; i++)
result += i;
for (int i = s; i <= e; i++)
Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.
(gdb)info b
Num
Type
1
breakpoint
Disp Enb Address
What
keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2
breakpoint
keep y
(gdb) n
0x0000555555555186
Breakpoint 2, Sum(s = 1, e = 100) at mycmd.c:9
9
result += i;
(gdb)n
7
(gdb)n
for (int i = s; i <= e; i++)
Breakpoint 2, Sum(s = 1, e = 100) at mycmd.c:9
9
result += i;
(gdb)
condition
(gdb) info b
Num
Type
2
i ==30
i ==
Disp Enb Address
in Sum at mycmd.c:9
30
What
breakpoint
keep y
1
Ox00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
breakpoint
keep y
2
Ox0000555555555186 in Sum at mycmd.c:9
stop only if i==30
breakpoint already hit 2 times
(gdb) n
7
for(int i = S; i <= e; i++)
(gdb) n
9
result += i;
(gdb) c
Continuing.
Breakpoint 2, Sum (s=1, e=1oo) at mycmd.c:9
9
result += i;
(gdb) p_
$1=30
(gdb) p result
$2=435
给已经存在的端点新增条件
📌 注意:
- 条件断点添加常见两种方式:1. 新增 2. 给已有断点追加
- 注意两者的语法有区别,不要写错了。
- 新增:
b 行号/文件名:行号/函数名 if i == 30
(条件)- 给已有断点追加:
condition 2 i == 30
,其中2是已有断点编号,没有if
后言
这就是开发工具git和gbd和cgbd的介绍和使用。大家自己好好消化!今天就分享到这! 感谢各位的耐心垂阅!咱们下期见!拜拜~