Linux中gcc、g++、gdb以及make/Makefile的使用

🍅Linux编译器gcc与g++🍅

我们习惯用gcc 编译C语言代码,g++编译C++的代码

gcc也可以编译Go语言程序之类的,gcc可以根据文件后缀来判断当前程序所用的语言

以test.c为例:

gcc -E test.c -o test.i 预处理:完成宏替换,去掉注释,头文件包含等工作

gcc -S test.i -o test.s 编译: 把C语言代码转化成汇编语言的代码

gcc -c test.s -o test.o 汇编:把汇编语言的代码转成机器语言(二进制序列)

gcc test.o -o mytest 链接:生成可执行程序(默认是动态链接)

🍅gcc演示🍅

下面对每步进行演示

📖①**vim test.c**

在这里插入图片描述

📖②gcc -E test.c -o test.i

-E 作用:预处理,但不生成文件

-o的作用:把生成的内容输出到文件,此外有给文件起名的作用

gcc -E test.c -o test.i 里的-o就是把预处理的内容输出到test.i里,不然直接打印到屏幕上了

cat -n test.i

test.i的内容

在这里插入图片描述

📖③gcc -S test.i -o test.s

-S:编译 ,不生成文件

-o 把生成的内容放入test.s

cat -n test.s

生成的汇编代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bUigwPn-1641739327072)(../typora 图片/image-20220109164421642.png)]

📖④gcc -c test.s -o test.o

-c 汇编不生成文件

-o 把生成的内容放入test.o

cat -n test.o

看不懂对吧,我也看不懂,可以转为二进制文件看

xxd test.o

在这里插入图片描述

看不懂对吧 我也看不懂🐱‍🏍

📖⑤gcc test.o -o mytest

这一步写成 gcc test.o -o mytest.exe 效果一样,Linux不是根据扩展名来给文件归类的,反正都是可执行文件,具有x权限

gcc test.o :链接 生成可执行文件.

mytest文件就不看了,和上面的test.o差不多,也是二进制文件

链接分为动态链接和静态链接,默认是动态链接

ldd和file可以判断链接类型

📖 ldd mytest

在这里插入图片描述

.so可以判断动态链接,.a判断是静态链接

libc.so.6就是个动态库,libc.a就表示是个静态库

在这里插入图片描述

📖file mytest

📖 英文时间:dynamically linked==动态链接
在这里插入图片描述

既然有动态链接 肯定就有静态链接 两者区别又是什么?

动态链接用到的是静态库,运行时加载库。

静态链接则是直接包含库,所以静态链接生成的文件会很大

怎么生成静态链接的可执行文件?

加-static

举例:gcc test.c -o mytest-s -static(如果报错了拉到下一个块解决报错)

生成的mytest-s就是静态链接的,看看具体信息

file mytest-s

在这里插入图片描述

📖 英文时间:statically linked==静态链接

📖 再比较下动态和静态库的大小

在这里插入图片描述

静态链接生成的文件大小是动态链接生成的100倍左右

不过静态链接也有优点,没有那么依赖配置环境,拿过来就能用。

不加-static默认是动态链接

🍅解决static报错问题🍅

报错信息:

/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

原因:少了静态库…搞了半天才解决

解决: sudo yum install glibc-static

把库给装上就完事了

补充:gcc -w 不生成任何警告

gcc -Wall 生成所有警告

我们默认是报警告的,所有默认是gcc -Wall

test.cpp test.cc test.cxx都表示c++文件

gcc编译器可以根据文件后缀判断文件的编程语言
英文时间: pwd==print work directory

🍅gdb的使用🍅

什么是gdb?

简单来说就是调试器,比如vs里的调试器

gdb 可执行程序

作用:进入调试

如gdb mytest

**如果报错:**重新生成可执行文件,gcc命令加上-g,不加默认release版本

gcc mytest -g

报错原因:文件里没有调试信息,也就是我们常说的release版本

gdb界面输入命令报错信息:No symbol table is loaded. Use the “file” command.

-g可加入调试信息 ,release版本无调试信息,不可被调试

检查当前文件是否具有调试信息

readelf -S mytest |grep debug

效果如图:(不打印则说明没有debug信息)
在这里插入图片描述

📖 小知识:为什么会有debug和release?

debug是给我们开发时用的,release一般是给用户用的
调试信息也占空间啊
如果只有debug版本,用户又不用调试,调试信息又多占了程序空间
所以对用户来说对debug的需求不强(没有)
如果只有release版本,自己感受一下出了bug没有调试器的感觉[doge]

📖 quit(q)或者ctrl+d:退出gdb

l :显示十行代码 按回车显示十行后的代码

但不一定是开头十行

📖 list (l) 行号:显示行号所在的代码

https://zhuanlan.zhihu.com/p/297925056,这个有关gdb的具体操作
在这里插入图片描述

📖 l 函数名 :显示函数的代码

📖 b 行号:给某行加断点 (b== Breakpoint )

如 b 7

📖 b 函数名:在函数入口加断点

📖 info b:列出所有断点

📖 r :开始调试 两次r重新调试 r ==run

📖 n : 逐过程(不会进入函数) n ==next

📖 p 变量:打印变量的值,但只显示一次

📖 print 表达式:打印表达式的值(变量也算入表达式)

📖 display 变量:长显示,每次n都会打印

​ 比如display sum 长显示sum,每次n都会显示sum的值

📖 undisplay 编号 取消长显示 注意是编号不是变量名

在这里插入图片描述
📖 where可以看到自己当前运行到多少行了。

📖 c (continue): 跳到下一个断点

📖 d 编号 :删除断点

在这里插入图片描述

📖 s 逐语句 :会进入函数,相对于的是n,逐语句运行,不进入函数

📖 bt :显示调用堆栈

📖 until 行号 跳转到函数里的任意位置

和断点有一些冲突

循环体:

for( i=0;i<=top;i++)
{
(断点)	 sum+=i;//断点启用时(走到这行了用until) until未能跳出循环
}

📖 finish 跑完当前函数 (官方点:执行到当前函数返回,然后停下来等待命令 非main函数)

在这里插入图片描述

📖 c until finish :跳转三剑客了属于是 🗡
一般就用这三个来跳转,分别对应跳到下一个断点,跳到任意行,执行完当前函数。

Enb=enable y表示断点可用
在这里插入图片描述

📖 disable 断点编号 :禁用断点

为啥要禁用断点呢,我不用直接删掉不就行了

答:保留调试痕迹,方便多次调试

📖 delete breakpoint 、delete breakpoints :删掉全部断点

set var 变量:改变调试时变量的值

比如set var i=100,用的比较少

注:改变变量的值不是VS里的条件断点,而是直接改变往后运行

🍅Linux项目自动化构建工具 -make/Makefile🍅

make:这是一条指令

makefile/Makefile:这是一个文件

依赖关系

gcc test.c -o test.exe
test.c
test.exe

test.exe的生成依赖于test.c

📖 touch makefile/touch Makefile

makefile里面写的是依赖关系和相应的操作

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

mytest:test.o 表示mytest依赖于test.o生成,表现出依赖关系
gcc test.o -o mytest gcc前面必须是Tab 不能是四个空格
test.o:test.s 表示test.o依赖于test.s生成,表现出依赖关系
gcc -c test.s -o test.o
test.s:test.i 表示test.s依赖于test.i生成,表现出依赖关系
gcc -S test.i -o test.s
test.i:test.c 表示test.i依赖于test.c生成,表现出依赖关系
gcc -E test.c -o test.i

📖 解释一下这个make吧 ,相当于一次性执行了多条命令,降低了我们的调试的成本

如果文件很多 写gcc一个一个编译链接过去成本太高

或者是软件迭代的时候,进行测试等操作时一个一个写gcc成本太高了

项目管理有生成文件的,自然就有删除文件的

📖 删除文件时makefile这么写:

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

📖 .PHONY:clean又是什么东西???

.PHONY很像一个声明,声明一下clean,或者说修饰一下clean

.PHONY定义伪目标,被修饰的clean总是被执行

⌨ 总是被执行?那肯定就有总是不被执行了

默认:总是不被执行

下面的make就是总是不被执行,即只能被执行一次,也一直提示make: `mytest’ is up to date.

同时对比clean
在这里插入图片描述

看到这还有一个问题

📖 为什么生成文件时只需要输入“make”而我在删除文件时却要输入“make clean”?

因为make就是从makefile文件由上往下走,执行第一条命令

这么说很晦涩,举个例子
在这里插入图片描述

全称就应该写 make mytest,只不过mytest相关命令写在clean前面,所以可以简写为make

如果把clean写在第一行,那make命令执行的就是删除功能了,有兴趣可以试试
此外make命令不会检查文件是否存在,找不到操作的文件就直接报错退出了

🍅简写makefile文件🍅

  1 mytest:test.o
  2   gcc $^ -o $@      $@依赖于$^,类似于代指
  3 test.o:test.s
  4   gcc -c $^ -o $@
  5 test.s:test.i
  6   gcc -S $^ -o $@
  7 test.i:test.c
  8   gcc -E $^ -o $@

在这里插入图片描述

末尾 📖

如果有帮助的话麻烦点个赞鼓励一下!

  • 40
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢乙醇的四氯化碳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值