gcc分别链接静态库和动态库生成可执行文件

本文分别通过链接静态库和动态库来编译可执行文件,在使用gcc编译的过程中了解链接静态库和动态库的区别与联系,同时深入理解Linux系统上是如何将源程序一步步的编译组装成可执行文件的。

(一)库文件

1.什么是库

本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。

  • 静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要该静态库。
  • 动态库在程序编译时并不会被链接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

2.库命名规则

  • 静态库
    静态库的名字一般为libxxx.a,其中xxx是该lib的名称。
  • 动态库
    动态库的名字一般为libxxx.so.major.minor,xxx是该lib的名称,major是主版本号, minor是副版本号。

3.查找依赖库

使用命令ldd可以查看一个可执行文件依赖的动态库。

$ ldd main
linux-vdso.so.1 (0x00007ffc42bcc000)
libx2.so => /usr/lib/libx2.so (0x00007ff37f0fc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff37ed0b000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff37f500000)

由此可见,main可执行文件依赖于linux-vdso、libx2、libc、ld-linux-x86-64这四个动态库。

(二)编译时链接静态库文件

1.源程序

  • main.c(主函数)
#include"sub1.h"
#include"sub2.h"
#include<stdio.h>

int main()
{
	int x=2,y=9,n;		//定义x和y变量
	printf("%d/%d=%.2f\n",y,x,x2x(x,y));	//输出处理后的值,保留两位小数
	printf("请输入斐波那契的第n项值:");
	scanf("%d",&n);
	printf("斐波那契数列第%d项为%d\n",n,x2y(n));	//输出斐波那契数列的第n项
	return 0;
}
  • sub1.h
#ifndef __SUB1_H
#define __SUB1_H

float x2x(int a,int b);		//计算b除以a

#endif

  • sub1.c(子函数1)
#include "sub1.h"

/*******************/
/*	参数:a	       */
/*	参数:b	   	   */
/*  返回值:b/a      */
/*******************/
float x2x(int a,int b)
{
	float ans;
	ans=(float)b/a;
	return ans;
}

  • sub2.h
#ifndef __SUB2_H
#define __SUB2_H

int x2y(int);	//计算斐波那契数列的第n项值

#endif
  • sub2.c(子函数2)
#include "sub2.h"

/*********************************/
/*		参数:n	   	 			 */
/*  返回值:第n项斐波那契数列值    	 */
/*********************************/
int x2y(int n)
{
	int a=1,b=1,i;
	long c=0;
	if(n<3) return 1;
	else
	{
		for(i=0;i<=n-3;i++)
		{
			c=a+b;
			a=b;
			b=c;
		}
		return c;
	}
}

2.编译静态库文件libx2.a

  • 编译.o目标文件
    输入命令gcc -c main.c sub1.c sub2.c可以编译得到main.o、sub1.o、sub2.o三个目标文件
    gcc-o
  • 编译libx2.a静态库文件
    使用命令ar -crv libx2.a sub1.o sub2.o编译生成libx2.a静态库文件。
    ar-a

3.链接为可执行文件main

  • 使用命令gcc main.o libx2.a -o main链接main.o和libx2.a文件生成可执行文件main
    gcc-main-a

  • 执行可执行文件main
    使用命令./main执行该可执行文件
    main运行

  • 测试是否真的静态库链接成功
    删除静态库libx2.a目标文件,再次执行该可执行文件
    rm-a
    以上说明静态库链接生成的可执行文件运行时不需要该静态库,因为该静态库已经被编译到可执行文件中了。

(三)编译时链接动态库文件

1.编译动态库文件libx2.so

.o目标文件已经在上面编译静态库文件时生成了,因此这里直接编译动态库文件。
使用命令gcc -shared -fPIC -o libx2.so sub1.o sub2.o编译生成动态库文件libx2.so
gcc-so

2.链接为可执行文件

  • 使用命令gcc main.o libx2.so -o main链接两个目标文件生成可执行文件main
    gcc-main-so
  • 执行生成的可执行文件main
    使用命令./main执行该可执行文件main
    • 发现报错如下:
      main-err
    • 原因:
      程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。
    • 解决方法:
      将libx2.so 复制到目录/usr/lib 中,再次执行./main运行(若提示权限不够则以使用sudo mv libx2.so /usr/lib该命令)
  • 使用命令ldd main查看main可执行文件的依赖项
    ldd

3。链接静态库与动态库生成可执行文件的区别

静态库生成的可执行文件为8520字节,动态库生成的可执行文件为8456字节。从而可见动态库生成的可执行文件要比静态库生成的要更小,但是链接动态库需要依赖于该动态库。

(四)总结

通过使用静态库和动态库分别链接生成可执行文件main,我深入的了解到了不同库函数的链接的作用是不一样的。静态库链接是直接在程序编译时就将其组装到一起,可以不依赖于静态库就能运行;而动态库链接是在程序运行时才将其载入内存运行且不能够缺少,否则不能运行。

感谢该博主我的启发:
关于Linux静态库和动态库的分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值