Linux环境基础开发工具使用(中)

Linux编译器-gcc/g++的使用

背景知识:

1、预处理 (进行宏替换)
2、编译 (生成汇编)
3、汇编 (生成及其可识别代码)
4、链接 (生成可执行文件或库文件)

gcc如何完成

Linux中编译器编译c语言使用gcc,使用gcc后在当前目录下生成a.out——可执行程序
运行这个程序就是:./a.out
在这里插入图片描述
注意:如果在编译不会有b.out、c.out等
Linux中运行程序是使用./ 解释:.代表当前,/是路径分隔符
直接输入a.out是不能够运行的,原因解释在进程后面会讲到。
在这里插入图片描述
如果输入当前路径名+a.out就可以直接运行——绝对路径

预处理(进行宏替换)

预处理(预处理指令是以#为开头的代码行)主要包括宏定义、文件包含、条件编译、去注释等

-E:预处理,形成的可执行程序可以进行自己指定名称
gcc -E mytest.c -o:代表指定形成一个可执行文件
-E:程序的翻译(预处理,编译,汇编,链接在这里统称为翻译)——完成程序的预处理后就停下,-E处理完后生成的临时文件后缀是.i
在这里插入图片描述
这样子,预处理的结果就在.i当中
在这里插入图片描述
在使用vs test.c可以同时观察两个文件
在这里插入图片描述
这样子我们就可以观察到:
在这里插入图片描述
头文件在这里就被展开
在这里插入图片描述
可以发现展开后就有800多行——因为头文件在编译时会被编译器直接拷贝进源文件中,所以才有防止头文件被重复包含的各种东西
总结:-E是让gcc在预处理后停止编译过程,-o是指目标文件,.i文件为已经经过预处理后的C原始程序

编译(生成汇编)

在这个阶段,gcc首先要检查代码的规范性、是否有语法错误等,已确定代码工作无误后,gcc才将代码生成汇编语言
用户可以使用-S选项来进行查看,该选项只进行编译不进行汇编,生成汇编代码
在这里插入图片描述
gcc -S mytest.c代表可以直接先预处理,然后编译,当然也可以直接从.i开始进行,这样子就不需要在经过预处理过程了
在这里-S之后默认可以不用带-o指明临时文件的名称,系统会默认生成一个同名.s
在这里插入图片描述

为了与前文一致,我们在这里也加上-o
在这里插入图片描述
在这里就可以查看mytest.s文件了
在这里插入图片描述
可以发现确实生成的是汇编
在这里插入图片描述
gcc中-S的意思就是开始进行程序的翻译,完成编译后停下,不往后进行

汇编(生成及其可识别代码)

汇编过程中就是将编译阶段生成的.s文件转化为目标文件,在此就可以使用-c就可以看到汇编代码已转化为.o的二进制目标代码

计算机可以直接执行汇编语言吗?汇编语言需要编译器吗?
不可以直接被执行,需要编译器
在这里插入图片描述
如果以.c文件为后缀,将预处理,编译,汇编一次做了
在这里插入图片描述
也就是默认由汇编语言生成二进制
在这里插入图片描述

可以使用查看二进制的工具来进行查询
在这里插入图片描述
在这里插入图片描述
然后尝试执行二进制文件发现也被拒绝了——没有权限
在这里插入图片描述
于是在这里加上x权限后尝试:
在这里插入图片描述
在这里插入图片描述
汇编形成的二进制文件并不可以直接执行——叫可重定向目标文件(不可以被直接执行,少了链接过程)
观察我们在vs下写的代码中就有.obj文件——等价于这里的.o文件
-c选项:开始进行程序的翻译,完成汇编工作后就停下

链接(生成可执行文件或库文件)

成功编译后就进入了链接阶段
语言也是有库的,一般是提供:一套头文件+一套库文件(libc.a,libc.so)动态库和静态库
需要链接来将我们自己代码中的函数调用还有外部数据和库关联起来,方便执行到这个代码直接执行库的代码
在这里插入图片描述
这样子就生成了可执行文件
如果想要自定义可执行程序的名字也可以使用-o
在这里插入图片描述
ESc——对应预处理,编译,汇编
当中生成的临时文件后缀是.iso

为什么C程序的翻译是这个过程?
最初是二进制编程——打孔编程
后来衍生为汇编语言(就有了助记符),汇编语言通过编译器将他转化为二进制
c语言也要变为二进制程序,是将c语言直接变成汇编和c直接转化为二进制哪一个更简单?——c语言直接变化为汇编语言
1、c语言有很多东西需要被提前处理(注释)
2、链接
链接如何理解?
把自己的代码与其他别人的库关联起来
ldd可以查看这个库
在这里插入图片描述
这个就是c的标准库
在这里插入图片描述
c语言包含头文件,链接这个库
在这里插入图片描述
这样子就可以查看c链接的标准库,libc-2.17.so
Linux中库分为静态库与动态库两种
静态库:.a结尾
动态库:.so结尾
Windows中的静态库与动态库后缀是:
静态库:.lib
动态库:.dll
因此链接就是将自己写的c语言程序和第三方库提供的方法相关联起来
因此就有静态链接与动态链接:
静态链接与动态链接
告诉你网吧在哪里就是链接过程,跑过去上网就是动态链接
图解动态链接:
在这里插入图片描述
库中的有关代码拷贝到我们自己的可执行程序中就叫做静态链接,这样子就不需要专门到库里面去找了
在这里插入图片描述
在这里插入图片描述
so为动态库,因此gcc默认采用动态链接方式,形成可执行程序
file可以查看mytest的特点,可以查看是动态链接
在这里插入图片描述
uses shared libs就是动态链接
如何静态链接?
在这里插入图片描述
这时候会发现报错了找不到 -lc 本质是云服务器没有安装静态库,可以查询centos7命令行安装c静态库libc.a

sudo yum install glibc-static

创建成功后执行他们两个,发现执行结果并没有显著区别:
在这里插入图片描述
想要静态链接,直接给gcc带static选项,这样子就默认静态链接了
在这里插入图片描述
因为动态链接不需要将库中的代码拷贝自己的可执行程序中,因此大小会小很多,节省内存硬盘的空间,下载传输强,确定,如果库丢失了,这个程序就无法在执行了
静态链接:程序体积很大,占磁盘内存空间

我们也可以自己查找自己安装的静态库
在这里插入图片描述
静态链接的时候,需要.a静态库
动态链接的时候,需要.so动态库

如何跑c++程序?
使用g++
使用g++ -v查看版本,gcc不能编译c语言
在这里插入图片描述
在这里插入图片描述
当然也可以跑其他语言程序,如脚本语言:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Linux调试器——gdb使用

gdb+可执行程序的名字就可以调试
进入这样子的模式后,输入ls等指令完全没有用
在这里插入图片描述

使用quit指令/ctrl+D即可退出
在这里插入图片描述
常用使用命令:
在这里插入图片描述在这里插入图片描述
输入l后发现提示没有符号被加载——原因没有任何调试信息,因此无法调试
在这里插入图片描述
输入以下命令:查看一个可执行程序的段构成
在这里插入图片描述
在这里插入图片描述
.data表示数据区
.bss表示未初始化区

Debug版本:如果一个程序是可以被调试的,那么这个程序的二进制文件中一定加入了一些debug信息,因此体积要比release大一些
Release版本:没有包含调试信息
centos中,默认的可执行程序是release版本,因此是不能调试
因此如果想要调试,需要在编译的时候加入-g选项
在这里插入图片描述使用以下指令查询可执行程序
在这里插入图片描述
此时可以发现明显的多了一些debug信息
在这里插入图片描述
在这里插入图片描述
总结:
gdb调试程序,必须是debug方式发布,也就是给gcc -g

发现这里是编译不通过的,因此在gcc后面加入
-std=c99
在这里插入图片描述

在这里插入图片描述
如果想要调试,一定要让程序先跑起来
下面演示调试步骤:
在这里插入图片描述
r就是run的缩写,让程序跑起来——相当于vs中的ctrl+f5快捷键
在这里插入图片描述
下来就开始学习第一条指令:l==list
在这里插入图片描述
想从第一行的位置开始显示代码,就输入l 1
在这里插入图片描述
在这之后继续输入list,行号会跟着
在这里插入图片描述
如果想要在16行打断点怎么操作?——一般是使用行号去打断点
b指令(breadpoint)+行号:打断点
在这里插入图片描述
info b:想看断点打的情况
在这里插入图片描述
其中enb表示启用
在输入r指令,运行的时候就到16行停下
到断点处停下
如果想进入函数内部怎么办?
指令s(step)就可以进入到函数的内部,在使用l指令查看这个函数,可以看到是从第五行开始
在这里插入图片描述
之后继续s(逐语句——相当于VS的F11)就可以一直往下一条一句
n(next表示逐过程——相当于VS的F10)
如果想看局部变量的值怎么办?
display指令(这个指令要写全,不能写缩写d)
在这里插入图片描述
display之后,这些变量的值不管是n还是s都会常显示
如果不想让他常显示,就输入p 变量名
如果不想看这个值了
undisplay 编号
在这里插入图片描述
在这里插入图片描述
如何出这个for循环,跑完这个函数
finish:直接跑完该函数
在这里插入图片描述
重新进行debug:r指令(redebug)
在这里插入图片描述
我们在第18行在打一个断点
在这里插入图片描述
这个信息表示:刚刚调试的过程中,第一个断点已经命中过了
在这里插入图片描述
c(continue)直接运行到下一个断点处
在这里插入图片描述
finish与continue的区别
finish:结束当前的函数
continue:直接到达下一个断点所在位置

在一个函数内部,可以使用until指令直接到达指定行
在这里插入图片描述

如果不想要某一个断点怎么办?
d(delete)+编号:删除断点
在这里插入图片描述
如果不想删除这个断点,只是禁用这个断点:
disable + 编号:直接禁用这个断点
在这里插入图片描述
如果想要打开这个断点:
enable + 编号:
在这里插入图片描述
一定要没事多用用gdb,不然面试考察打断点/去断点等就不会了

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值