目录
一:Linux编译器-gcc/g++
预处理-编译-汇编-链接
1.预处理
2.编译 (生成汇编)
3.汇编(生成机器可识别代码)
4.链接(生成可执行文件或库文件)
三:动静态链接和动静态库
动静态库
动静态链接
1.动态链接
2.静态链接
3.注意点
4.各自优缺点
5.ldd和file指令
四:debug和release,readelf指令
接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧
一:Linux编译器-gcc/g++
1.对于gcc只能编译c语言代码,g++既能编译c语言代码也能编译c++代码,但g++主要编译c++
2.常用形式 gcc/g++ 文件名,此时就会形成a.out的可执行文件,再./a.out
3.也可以根据以下方式来书写
gcc 源文件名 -o 目标文件名(推荐写法)(一步到位,下面的是分步处理)
gcc -o 目标文件名 源文件名
4.对于为啥我们直接能够在windows/Linux中进行 c/c++等的开发呢?
最重要的是我们的系统中一定要提前或者后续安装上c/c++开发相关的头文件,库文件
对于c/c++中起始的几行都是c/c++的头文件,这些头文件在预处理时会全部展开,而对于具体的调用的函数如printf,就得调用c/c++标准库的库函数来完成对应的操作
所以只要系统安装了相关的头文件和库文件就可以完成c/c++的开发,具体的来说就是c/c++开发环境不仅仅指的是vs,gcc,g++这些,更重要的是语言本身的头文件和库文件
因此对于编译型的语言,安装开发包,必定是下载安装包对应的头文件和库文件
Linux下的头文件路径 --gcc/g++编译时的默认搜索路径
预处理-编译-汇编-链接
1.预处理
预处理阶段完成的是宏调换,去注释,头文件展开,条件编译等操作,仍是c代码
gcc表示格式:gcc -E 源文件名 -o 以.i结尾的目标文件
-E:告诉gcc,从现在开始进行程序的翻译,将预处理工作做完就停下来,不用往后继续执行
2.编译 (生成汇编)
在这个阶段gcc要检查代码的规范性,是否有语法错误等,在检查无误后,将c代码翻译为汇编语言
gcc表示格式:gcc -S 源文件名 -o 以.s结尾的目标文件
-S:告诉gcc,从现在开始进行程序的翻译,将编译工作做完就停下来,不用往后继续执行
3.汇编(生成机器可识别代码)
gcc表示格式:gcc -c 源文件名 -o 以.o结尾的目标文件
-c:告诉gcc,从现在开始进行程序的翻译,将汇编工作做完就停下来,不用往后继续执行
.o结尾的这个文件叫做可重定位目标二进制文件,简称目标文件,就是windows中的.obj文件
不需要独立执行,虽然是二进制的但仍需要经过连接才能执行
4.链接(生成可执行文件或库文件)
将可重定位目标二进制文件和库进行链接形成可执行程序
作用:在我们的c程序中,对于printf 这样的库函数,在预编译时的展开的头文件里也只有函数的声明,没有实现,那么是在哪里实现的呢?----------答案是系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统的默认搜索路径/usr/lib下查找,也就是链接到libc.so.6库函数中去,这样便实现了printf函数
gcc表示格式:gcc -c 源文件 -o 目标文件
三:动静态链接和动静态库
1.库的理解
库其实是给我们提供方法的实现,如上面的对于printf函数的实现就是在库中实现的,而这个库也就是c标准库,本质也是文件,也有对应的路径
动静态库
1.在Linux和windows都将库分为静态库和动态库,两者只有命名方式上的不同
Linux中:.so(动态库) .a(静态库) windows : .dll(动态库) .lib(静态库)
静态库是指编译链接时,把库文件的代码全部加入到可执行文件中
动态库:在程序执行时由运行时链接文件加载库,只加载所需要的,节省空间大小
2.命名规则:libname.so.xxx,name为c就是c库,c++就是c++库
3.在Linux中只会安装动态库,而静态库需要自己安装
sudo yum install -y glibc-static(c静态库) sudo yum install -y libstdc++-static(c++静态库)
4.库的作用
根据上面得知,方法的实现就在库当中,库就是将源文件(.c)经过一定的翻译,然后打包,封装然后只提供一个所需的文件,而将其他源文件隐藏
具体的软件的实现=头文件中的方法声明+库文件提供的方法实现+具体代码
5.由于gcc编译时默认使用的是动态库,完成的是动态链接,如要实现静态链接就要添加-static
动静态链接
这里先举个鲜明的例子来帮助铺垫和理解
1.动态链接
动态链接就是当可执行程序自己完成不了时,就需要跳转到库中,执行库中的方法,执行完后再进行返回
特点:拷贝的是在哪里实现,不拷贝具体的实现方法;动态库只需要一个;可执行程序依旧依赖库;一旦缺失动态库,会影响很多的可执行程序无法正常运行
2.静态链接
编译器使用静态库进行静态链接时,会将静态库的所有方法实现拷贝到可执行程序中,使该程序不再依赖静态库
3.注意点
1.如果我们没有静态库,但就要-static ,是不行的
2.如果没有动态库,但有静态库,而且gcc能找到,这个是可以的; 因为gcc默认优先动态链接, 而-static的本质就是改变优先级,使所有链接要求变为静态链接,并且只能适配一次
3.所有的链接都是静态链接和动态链接混合使用的
4.各自优缺点
动态库:优:因为是共享库,可以有效的节省资源(磁盘空间,内存空间,网络空间等)
缺:一旦缺失,导致各个程序都无法运行
静态库:优:不依赖库,程序可以独立运行
缺:体积大,比较消耗资源
5.ldd和file指令
ldd 是查询文件依赖的动态库 ldd 文件名
file 查询可执行程序是动态链接还是静态链接 file 文件名
四:debug和release,readelf指令
1.gcc默认编译出来的是release版本
2.对于debug版本因为在形成可执行程序时,添加了debug信息,是可以被追踪调试
3.debug版本 只需添加-g 选项即变为debug版本
4. readlf指令
readelf -S 文件名 | grep -i debug 查看添加的debug信息
readelf -S 文件名 读取可执行程序的对应二进制构成