Linux学习笔记2 c语言编译与调试| 库文件

一,c语言程序在linux系统的使用

在Linux中我们没有类似vs2022和vscode之类的编译器,我们使用的是gcc去编译我们的代码

1,gcc分步编译链接

(1) 预编译 : gcc -E main.c -o main.i

(2) 编译: gcc -S main.i -o main.s

(3) 汇编: gcc -c main.s -o main.o  

(4) 链接: gcc main.o -o main

gcc的一步编译通常使用gcc  test.c -o main 

2,编译链接过程

所以的c语言程序都会经过预编译,编译,汇编,链接四个步骤,从而将文本文件转化成可执行程序。

3,预编译阶段

a) 删除所有的“#define”,并且展开所有的宏定义;

b) 处理所有的条件预编译指令,“#if”、“#ifdef”、“#endif”等;

c) 处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置;

d) 删除所有的注释;

e) 添加行号和文件名标识,以便于编译器产生调试用的符号信息及编译时产生编译错 误和警告时显示行号;

f) 保留所有的#pragma 编译器指令,因为编译器需要使用它们。

3.2 编译阶段

词法分析、语法分析、语义分析,代码优化,汇总符号。

3.3 汇编阶段

将汇编指令翻译成二进制格式,生成各个 section,生成符号表。

3.4 链接阶段

a) 合并各个 section,调整 section 的起始位移和段大小,合并符号表,进行符号解析, 给符号分配虚拟地址

b) 符号重定位

4、makefile 和 make

在linux中如果有多个文件需要编译,一个个去编译是很麻烦的,所以我们可以去使用make命令一部编译,具体操作如下

对 main.c add.c max.c 三个文件进行编译(注意: gcc 前面必须是 table 建缩进)

clean是为了删除多余的不必要文件。

make 命令根据 makefile 文件的规则生成可执行程序

5、gdb 调试

5.1 Debug 版本和 Release 版本

Debug 版本

Debug 版本为可调式版本,生成的可执行文件中包含调试需要的信息。我们作为开发人 员,最常用的就是 debug 版本的可执行文件。

Debug 版本的生成:

因为调试信息是在编译过程时加入到中间文件(.o)中的,所以必须在编译时控制其生 成包含调试信息的中间文件。

gcc -o hello hello.c -g

Release 版本

Release 版本为发行版本,是提供给用户使用的版本。用 gcc 默认生成的就是 Release 版本。

首先将源代码编译、链接生成 Debug 版本的可执行文件,然后通过‘gdb Debug 版本 的可执行文件名’进入调试模式。

5.2 单进程、单线程基础调试命令

二,库文件

1、什么是库文件

库是一组预先编译好的方法的集合。

Linux系统存储的库的位置一般在:/lib 和 /usr/lib。

在 64 位的系统上有些库也可能被存储在/usr/lib64 下。库的头文件一般会被存储在 /usr/include 下或其子目录下。

库有两种,一种是静态库,其命令规则为 libxxx.a,一种是共享库,其命令规则为 libxxx.so。

2、静态库的生成与使用

2.1 静态库的生成

以下是需要生成静态库的”.c”文件,其中“foo.h”中是函数的声明,“add.c”和“max.c” 是函数的定义

第一步:先将需要生成库文件的所有“.c“文件编译成“.o”文件

第二步:使用 ar 命令将第一步编译的所有”.o”文件生成静态库,其中: ◼ c 是创建库 ◼ r 是将方法添加到库中 ◼ v 显示过程

2.2 静态库的使用

以下是测试代码”main.c”中的内容:

以下是使用静态库“libfoo.a”和“main.c”生成可执行文件的过程,其中:

◼ -L 指定库的存储路径

◼ -l 指定库的名称(不需要前面的‘lib’和扩展名‘.a’)

3、共享库的生成与使用

3.1 共享库的生成

以下是需要生成共享库的”.c”文件,其中“foo.h”中是函数的声明,“add.c”和“max.c” 是函数的定义

第一步:先将需要生成库文件的所有“.c“文件编译成“.o”文件

第二步:使用 gcc 命令将第一步编译的所有”.o”文件生成共享库

3.2 共享库的使用

以下是测试代码”main.c”中的内容:

以下是使用共享库“libfoo.so”和“main.c”生成可执行文件的过程,其中 -L 指定库的 存储路径, -l 指定库的名称(不需要前面的‘lib’和扩展名‘.so’), 如果在库的存储路径 有同名的共享库和静态库,gcc 默认使用共享库。

生成之后,直接执行 main 程序,发现出错,原因是系统加载共享库时,找不到对应的 共享库文件”libfoo.so”, 但是该库确实在当前目录下存在。这是为什么呢?因为系统默认 只会去存储库的标准位置(/lib 或/usr/lib 等)加载,而不会在当前位置寻找。所以将库拷贝到 /usr/lib 下,再执行程序,就可以成功。 如果库不在标准位置下,也可以通过设置环境变量”LD_LIBRARY_PATH”来指定加 载库的路径。

4、静态库和共享库的区别

静态库在链接时将用到的方法包含到最终生成的可执行程序中,而共享库不包含,只做 标记,在运行程序时,才动态加载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值