目录
一、gcc/g++
1、预处理
2、编译
3、汇编
4、gcc选项
二、动静态库
三、Linux项目自动化构建工具-make/Makefifile
四、yum
1、yum list
2、yum install 安装软件
3、yum remove
五、git
六、gdb
1、背景认识
2、gdb选项
总结
一、gcc/g++
任何一段C/C++程序转变为可执行程序都要经历编译链接。
编译分为预处理,编译,汇编,三个过程
头文件的包含 #include
#define定义符号的替换
注释删除
文本操作
将C/C++语言代码翻译成了汇编代码
语法分析
词法分析
语义分析
符号汇总
把汇编指令翻译成了二进制指令
形成符号表
-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面-S 编译到汇编语言不进行汇编和链接-c 编译到目标代码-o 文件输出到 文件-static 此选项对生成的文件采用静态链接-g 生成调试信息。GNU 调试器可利用该信息。-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.-O0-O1-O2-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高-w 不生成任何警告信息。-Wall 生成所有警告信息
gcc只能用来编译c语言,g++既可编译c语言又可编译c++
编译的三个过程gcc选项可以简化为ESc 与之所对应的形成文件的后缀是iso
C程序是离不开C库文件的
可以使用idd或者file命令查看动静态库信息
[WW@VM-8-14-centos testFork]$ ls
a.out test.c
[WW@VM-8-14-centos testFork]$ ldd a.out
linux-vdso.so.1 => (0x00007ffcf94ae000)
/$LIB/libonion.so => /lib64/libonion.so (0x00007feb24e95000)
libc.so.6 => /lib64/libc.so.6 (0x00007feb249ae000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007feb247aa000)
/lib64/ld-linux-x86-64.so.2 (0x00007feb24d7c000)
首先要明确一点
Linux下动态库的后缀是.so 静态库的后缀是.a
Windows下动态库.dll 静态库后缀是.lib
我们可以看到gcc默认是以动态库的方式进行编译
正如每次写C语言或者C++时都要引用头文件,.h文件只是包含函数或者其它变量的声明
具体的实现方法在动静态库中,我们引用的stdio.h中也是同样的
动态链接:将库中我要的方法地址填入到我的可执行程序中,建立关联节省资源
静态链接:将库中方法的实现,拷贝到可执行程序中,占用较多资源
[WW@VM-8-14-centos testFork]$ gcc -o test_static test.c -static
[WW@VM-8-14-centos testFork]$ ls
a.out test.c test_static
[WW@VM-8-14-centos testFork]$ gcc -o test_dynamic test.c
[WW@VM-8-14-centos testFork]$ ls -als
total 884
4 drwxrwxr-x 2 WW WW 4096 Aug 1 09:36 .
4 drwxrwxr-x 4 WW WW 4096 Aug 1 08:58 ..
12 -rwxrwxr-x 1 WW WW 8456 Aug 1 09:01 a.out
4 -rw-rw-r-- 1 WW WW 180 Aug 1 09:01 test.c
12 -rwxrwxr-x 1 WW WW 8456 Aug 1 09:36 test_dynamic
848 -rwxrwxr-x 1 WW WW 866248 Aug 1 09:36 test_static
我们会发现两中编译方式产生的文件体积差距明显,基本相差100倍。
我们的机器可能会因为没有静态库而导致链接失败
动态链接必须使用动态库,静态链接必须使用静态库
Makefile 文件描述了 Linux 系统下 C/C++ 工程的编译规则,它用来自动化编译 C/C++ 项目。一旦写编写好 Makefile 文件,只需要一个 make 命令,整个工程就开始自动编译,不再需要手动执行 GCC 命令。
一个中大型 C/C++ 工程的源文件有成百上千个,它们按照功能、模块、类型分别放在不同的目录中,Makefile 文件定义了一系列规则,指明了源文件的编译顺序、依赖关系、是否需要重新编译等。
我们在编写一个工程时会将每一个源文件进行编译,每次都要输入gcc或者g++命令,十分繁琐,当我们改动一个文件时可能需要重新编译这些文件,十分的繁琐。我们使用makefile就可以轻松解决这个问题了。
make是一个命令,makefile是一个文件
Stack:Stack.c test.c
gcc -o Stack -g Stack.c test.c
.PHONY:clean
clean:
rm -f Stack
这是我们简单编写的一个makefile,makefile从上往下扫描,遇到第一个目标就停止
想要执行其它目标,可以使用make +目标名
.PHONY是一个伪目标,它是总是被执行的,可以将编译命令设置为伪目标,重复生成可执行程序。
当我们重复make时会出现以下情况
[WW@VM-8-14-centos test]$ make
make: `Stack' is up to date.
它是怎么确定我们的文件是最新的呢?
我们知道文件有acm时间,源文件的修改时间一定是早于可执行文件的修改时间的,因为源文件编译之后才会生成可执行文件。也就是说可执行文件的修改时间是最晚的。它可以通过判断修改时间来确认可执行程序是否是最新的。
在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序.但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行安装.软件包和软件包管理器, 就好比 "App" 和 "应用商店" 这样的关系.yum(Yellow dog Updater, Modifified)是Linux下非常常用的一种包管理器. 主要应用在Fedora, RedHat,Centos等发行版上.
yum就好比手机上的应用市场,yum可以用来搜索,下载,安装 软件 同时解决依赖关系
yum三板斧
zinnia-tomoe-ja.x86_64 0.06-22.el7 epel
zinnia-tomoe-zh_CN.x86_64 0.06-22.el7 epel
zinnia-utils.x86_64 0.06-22.el7 epel
zipios++.x86_64 0.1.5.9-9.el7 epel
zipios++-devel.x86_64 0.1.5.9-9.el7 epel
zlib.i686 1.2.7-20.el7_9 updates
zlib-ada.x86_64 1.4-0.5.20120830CVS.el7 epel
zlib-ada-devel.x86_64 1.4-0.5.20120830CVS.el7 epel
zlib-devel.i686 1.2.7-20.el7_9 updates
zlib-static.i686 1.2.7-20.el7_9 updates
zlib-static.x86_64 1.2.7-20.el7_9 updates
zmap.x86_64 2.1.1-1.el7 epel
znc.x86_64 1.8.2-1.el7 epel
znc-devel.x86_64 1.8.2-1.el7 epel
znc-modperl.x86_64 1.8.2-1.el7 epel
znc-modpython.x86_64 1.8.2-1.el7 epel
znc-modtcl.x86_64 1.8.2-1.el7 epel
zopfli.x86_64 1.0.1-1.el7 epel
zork.x86_64 1.0.3-1.el7 epel
zsh.x86_64 5.0.2-34.el7_8.2 os
zsh-html.x86_64 5.0.2-34.el7_8.2 os
zsh-lovers.noarch 0.9.0-1.el7 epel
zsh-syntax-highlighting.noarch 0.7.1-1.el7 epel
zstd.x86_64 1.5.2-1.el7 epel
zulucrypt.x86_64 5.0.1-1.el7 epel
zulucrypt-console.x86_64 5.0.1-1.el7 epel
zulucrypt-devel.x86_64 5.0.1-1.el7 epel
zulucrypt-doc.noarch 5.0.1-1.el7 epel
zulucrypt-libs.x86_64 5.0.1-1.el7 epel
zvbi.x86_64 0.2.35-1.el7 epel
zvbi-devel.x86_64 0.2.35-1.el7 epel
zvbi-fonts.noarch 0.2.35-1.el7 epel
zziplib.i686 0.13.62-12.el7 os
zziplib.x86_64 0.13.62-12.el7 os
zziplib-devel.i686 0.13.62-12.el7 os
zziplib-devel.x86_64 0.13.62-12.el7 os
zziplib-utils.x86_64
yum list 列出所有可安裝的软件清单命令
sudo yum install -y sl
[WW@VM-8-14-centos test]$ sudo yum install -y sl
[sudo] password for WW:
Loaded plugins: fastestmirror, langpacks
Repository epel is listed more than once in the configuration
Determining fastest mirrors
epel | 4.7 kB 00:00:00
extras | 2.9 kB 00:00:00
os | 3.6 kB 00:00:00
updates | 2.9 kB 00:00:00
(1/7): epel/7/x86_64/updateinfo | 1.1 MB 00:00:00
(2/7): epel/7/x86_64/group_gz | 97 kB 00:00:00
(3/7): os/7/x86_64/group_gz | 153 kB 00:00:00
(4/7): extras/7/x86_64/primary_db | 247 kB 00:00:00
(5/7): os/7/x86_64/primary_db | 6.1 MB 00:00:00
(6/7): updates/7/x86_64/primary_db | 16 MB 00:00:00
(7/7): epel/7/x86_64/primary_db | 7.0 MB 00:00:01
Resolving Dependencies
--> Running transaction check
---> Package sl.x86_64 0:5.02-1.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
===========================================================================================================================================================================================
Package Arch Version Repository Size
===========================================================================================================================================================================================
Installing:
sl x86_64 5.02-1.el7 epel 14 k
Transaction Summary
===========================================================================================================================================================================================
Install 1 Package
Total download size: 14 k
Installed size: 17 k
Downloading packages:
sl-5.02-1.el7.x86_64.rpm | 14 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : sl-5.02-1.el7.x86_64 1/1
Verifying : sl-5.02-1.el7.x86_64 1/1
Installed:
sl.x86_64 0:5.02-1.el7
Complete!
安装软件一般需要root权限所以加上sudo
这样就安装好了sl,我们运行一下
移除软件
我们可以尝试将sl软件删除
[WW@VM-8-14-centos test]$ sudo yum remove sl
Loaded plugins: fastestmirror, langpacks
Repository epel is listed more than once in the configuration
Resolving Dependencies
--> Running transaction check
---> Package sl.x86_64 0:5.02-1.el7 will be erased
--> Finished Dependency Resolution
Dependencies Resolved
===========================================================================================================================================================================================
Package Arch Version Repository Size
===========================================================================================================================================================================================
Removing:
sl x86_64 5.02-1.el7 @epel 17 k
Transaction Summary
===========================================================================================================================================================================================
Remove 1 Package
Installed size: 17 k
Is this ok [y/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Erasing : sl-5.02-1.el7.x86_64 1/1
Verifying : sl-5.02-1.el7.x86_64 1/1
Removed:
sl.x86_64 0:5.02-1.el7
Complete!
这样就把sl删除了
我们再运行就会出现以下情况,找不到文件或目录
[WW@VM-8-14-centos test]$ sl
-bash: /usr/bin/sl: No such file or directory
git是一个版本控制工具。
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
git三板斧
预备:
git clone你的仓库链接
git add 文件名 #添加代码到本地仓库
git commit -m "提交日志" #提交代码到本地仓库
git push 提交代码到远端仓库
[WW@VM-8-14-centos test]$ git add 8.1
[WW@VM-8-14-centos test]$ git commit -m "PID相关内容练习"
[main f2a1509] PID相关内容练习
6 files changed, 30 insertions(+)
create mode 100755 8.1/testFork/a.out
create mode 100644 8.1/testFork/test.c
create mode 100755 8.1/testFork/test_dynamic
create mode 100755 8.1/testFork/test_static
create mode 100755 8.1/testPID/a.out
create mode 100644 8.1/testPID/test.c
[WW@VM-8-14-centos test]$ git push
warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:
git config --global push.default matching
To squelch this message and adopt the new behavior now, use:
git config --global push.default simple
See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)
Username for 'https://gitee.com': 你的代码托管平台账号
Password for 'https://@gitee.com': 密码
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (10/10), 349.59 KiB | 0 bytes/s, done.
Total 10 (delta 2), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
To https://gitee.com/wang_wei15144991472/test.git
cf85611..f2a1509 main -> main
其它情况:第一次使用需要配置用户名和邮箱
git config --global user.email 你的邮箱
git config --global user.name 你的用户名
有时候无法提交,可能是版本冲突,你的本地代码与云端的代码有差异
git只会记录变化的部分,这时无脑git pull
GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c++程序员,gdb是必不可少的工具;
gdb是一个命令行下的调试器
gcc和g++默认形成的可执行程序是release版本的,所以无法直接被调试
我们在编译时使用-g选项,将程序编译为debug版本
[WW@VM-8-14-centos test]$ readelf -S Stack
There are 35 section headers, starting at offset 0x3670:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002b8 000002b8
00000000000000d8 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400390 00000390
0000000000000064 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 00000000004003f4 000003f4
0000000000000012 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400408 00000408
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400428 00000428
0000000000000018 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000400440 00000440
00000000000000c0 0000000000000018 AI 5 23 8
[11] .init PROGBITS 0000000000400500 00000500
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000400520 00000520
0000000000000090 0000000000000010 AX 0 0 16
[13] .text PROGBITS 00000000004005b0 000005b0
0000000000000572 0000000000000000 AX 0 0 16
[14] .fini PROGBITS 0000000000400b24 00000b24
0000000000000009 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 0000000000400b30 00000b30
000000000000008a 0000000000000000 A 0 0 8
[16] .eh_frame_hdr PROGBITS 0000000000400bbc 00000bbc
0000000000000074 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000400c30 00000c30
00000000000001f4 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 0000000000601e10 00001e10
0000000000000008 0000000000000008 WA 0 0 8
[19] .fini_array FINI_ARRAY 0000000000601e18 00001e18
0000000000000008 0000000000000008 WA 0 0 8
[20] .jcr PROGBITS 0000000000601e20 00001e20
0000000000000008 0000000000000000 WA 0 0 8
[21] .dynamic DYNAMIC 0000000000601e28 00001e28
00000000000001d0 0000000000000010 WA 6 0 8
[22] .got PROGBITS 0000000000601ff8 00001ff8
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 0000000000602000 00002000
0000000000000058 0000000000000008 WA 0 0 8
[24] .data PROGBITS 0000000000602058 00002058
0000000000000004 0000000000000000 WA 0 0 1
[25] .bss NOBITS 000000000060205c 0000205c
0000000000000004 0000000000000000 WA 0 0 1
[26] .comment PROGBITS 0000000000000000 0000205c
000000000000002d 0000000000000001 MS 0 0 1
[27] .debug_aranges PROGBITS 0000000000000000 00002089
0000000000000060 0000000000000000 0 0 1
[28] .debug_info PROGBITS 0000000000000000 000020e9
0000000000000448 0000000000000000 0 0 1
[29] .debug_abbrev PROGBITS 0000000000000000 00002531
00000000000001c5 0000000000000000 0 0 1
[30] .debug_line PROGBITS 0000000000000000 000026f6
000000000000013d 0000000000000000 0 0 1
[31] .debug_str PROGBITS 0000000000000000 00002833
0000000000000160 0000000000000001 MS 0 0 1
[32] .symtab SYMTAB 0000000000000000 00002998
0000000000000858 0000000000000018 33 59 8
[33] .strtab STRTAB 0000000000000000 000031f0
0000000000000336 0000000000000000 0 0 1
[34] .shstrtab STRTAB 0000000000000000 00003526
0000000000000148 0000000000000000 0 0 1
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)
我们使用readelf命令可以发现Stack以-g选项编译后程序中出现了debug信息
list :以默认形式显示代码
quit:退出gdb
r:开始调试,如果没有设置断点,就直接运行结束
b + 行号:给特定的行号打断点
info b:查看断点
d:删除断点
n:逐过程
s:逐语句
p + 变量名:打印变量内容
bt:查看函数调用堆栈
finish:将当前函数跑完
display:设置长显示
undisplay:取消长显示
until:跳转到指定行
c:运行到下一个断点停下来
显示代码
(gdb) l 0
1 #include"Stack.h"
2
3 void test1()
4 {
5 ST st;
6 StackInit(&st);
7 printf("%d \n", StackSize(&st));
8 StackPush(&st, 1);
9 StackPush(&st, 2);
10 StackPush(&st, 3);
(gdb)
11 StackPush(&st, 4);
12 StackPush(&st, 5);
13 printf("%d \n", StackSize(&st));
14 while (!StackEmpty(&st))
15 {
16 printf("%d ", StackTop(&st));
17 StackPop(&st);
18 }
19
20 printf("%d \n", StackSize(&st));
(gdb)
21 StackDestroy(&st);
22
23
24 }
25
26 int main()
27 {
28 test1();
29 return 0;
30 }
(gdb)
Line number 31 out of range; test.c has 30 lines.
设置断点,查看断点
Line number 31 out of range; test.c has 30 lines.
(gdb) b 3
Breakpoint 1 at 0x40098a: file test.c, line 3.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040098a in test1 at test.c:3
调用堆栈
(gdb) bt
#0 test1 () at test.c:6
#1 0x0000000000400a9c in main () at test.c:28
打印变量内容
(gdb) p st
$1 = {a = 0x400ab0 <__libc_csu_init>, top = 4195760, capacity = 0}
以上就是今天要讲的内容。