静态库与动态库的基础知识手册
静态库和动态库编译

静态库和动态库编译静态库和动态库是编程中常用的两种库文件形式,本文将介绍它们的编译过程和使用方法。
1. 静态库编译静态库是一种在编译时被链接到程序中的库文件,它包含了程序所依赖的所有函数和数据结构,因此程序在运行时不需要再加载库文件。
静态库的编译过程包括以下步骤:(1)创建一个或多个源文件,使用编译器将它们编译成目标文件(.o 或 .obj)。
(2)将多个目标文件打包成一个静态库文件,通常使用 ar 工具完成此操作。
例如,在 Linux 系统下,可以使用以下命令创建名为 libfoo.a 的静态库文件:$ ar rcs libfoo.a foo1.o foo2.o ...其中,rcs 参数分别表示创建、向库文件中添加目标文件和生成索引表。
(3)在编译器中使用静态库,需要将其链接到目标程序中。
在Linux 系统下,可以使用以下命令编译名为 main.c 的源文件和名为libfoo.a 的静态库文件:$ gcc -o main main.c -L. -lfoo其中,-L 参数指定库文件搜索路径,. 表示当前目录;-l 参数指定链接库文件,实际上是将其前缀 lib 和后缀 .a 去掉,即 foo。
2. 动态库编译动态库是一种在程序运行时动态加载的库文件,它只包含程序所需要的部分函数和数据结构,因此可以减小程序的尺寸和加载时间。
动态库的编译过程包括以下步骤:(1)创建一个或多个源文件,使用编译器将它们编译成目标文件。
(2)将多个目标文件打包成一个共享库文件,通常使用 ld 或链接器完成此操作。
例如,在 Linux 系统下,可以使用以下命令创建名为 libfoo.so 的动态库文件:$ gcc -shared -o libfoo.so foo1.o foo2.o ...其中,-shared 参数表示生成共享库文件。
(3)在编译器中使用动态库,需要将其链接到目标程序中。
在Linux 系统下,可以使用以下命令编译名为 main.c 的源文件和名为libfoo.so 的动态库文件:$ gcc -o main main.c -L. -lfoo其中,-L 和 -l 参数的含义同静态库。
动态库与静态库的异同

动态库与静态库的异同、生成和使用详解
分类:基于Linux的C/C++程序开发2012-12-05 11:11 501人阅读评论(0) 收藏举报生成和调用静态库与动态库静态库与动态库的区别静态库和动态库
下面表格实例中,实现了把test模块分别生成动态库(libtest.so)和静态库(libtest.a),并使用了生成的库。
详情和注解如下:
注解:
test.c -----测试功能模块的c文件
test.h -----测试功能模块的头文件
main.c -----include“test.h”的主函数文件
-share -----该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。
相当于一个可执行文件。
-fPCI -----表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不
能达到真正代码段共享的目的。
注解A:在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc 命令生成目标文件时指明静态库名,gcc 将会从静态库中
将公用函数连接到目标文件中。
注意,gcc 会在静态库名前加上前缀lib,然后追加扩展名.a 得到的静态库文件名来查找静态库文件。
C语言动态库与静态库区别

C语言动态库与静态库区别在C语言开发中,库(Library)是一种可重用的代码模块,它包含了一系列已经编译的函数和数据,用于帮助开发人员快速完成特定的任务。
库分为动态库和静态库两种形式,它们在使用方式和编译过程中存在一些显著的区别。
一、动态库(Dynamic Library)动态库也被称为共享库(Shared Library),其扩展名一般为“.so”(在Windows系统下为“.dll”)。
动态库在程序运行时被加载到内存,可以被多个程序实例共享,使得内存利用率更高。
而且,由于动态库在编译时并未与目标程序绑定,因此可以通过动态链接器在程序运行时加载、卸载和更新,具有更高的灵活性。
动态库的特点如下:1. 内存占用:动态库在程序运行时才会被加载到内存,因此不会增加目标程序的体积。
多个程序实例可以共享同一个动态库,节省内存空间。
2. 更新维护:对于动态库的更新和维护,只需要替换库文件即可,无需重新编译目标程序。
3. 运行时加载:动态库的加载和卸载是在程序运行时完成的,可以根据需要进行动态加载和卸载,提高程序的灵活性。
4. 共享性:多个程序实例可以同时使用同一个动态库,提高代码的重用性,并且减少了库文件的重复。
二、静态库(Static Library)静态库是在编译目标程序时,将库的代码和数据直接复制到目标程序中。
静态库的文件扩展名通常为“.a”(在Windows系统下为“.lib”)。
由于静态库在编译时与目标程序绑定,因此静态库的代码和数据会被完整复制到每一个使用该库的程序中。
静态库的特点如下:1. 执行速度:由于静态库的代码和数据完全被复制到了目标程序中,因此在执行过程中不需要进行动态加载,执行速度相对较快。
2. 独立性:每一个使用该库的程序都包含了静态库的完整副本,因此静态库程序可以独立运行,无需依赖其他库文件。
3. 目标文件较大:由于静态库代码和数据完全被复制到目标程序中,所以会导致目标文件体积较大。
头文件和库文件-静态库和动态库

头⽂件和库⽂件-静态库和动态库⼀、头⽂件和库⽂件头⽂件提供声明,库⽂件提供定义/实现。
C代码的编译过程: 预处理(需要头⽂件) -> 编译 -> 汇编 -> 链接(需要库⽂件); 执⾏时可能还有动态链接过程。
编译的时候,只要有头⽂件中的声明就⾜够了。
在链接的时候,把已经编译好的.obj和现有的.lib⽂件进⾏链接,这时就可以最终⽣成可执⾏⽂件了。
其实头⽂件与其实现⽂件或相应lib⽂件都没有直接的联系。
头⽂件是告诉编译器函数是如何去调⽤如何返回的,所有实现都是分别编译,最后在链接阶段链在⼀起。
头⽂件包含声明, 库⽂件包含实现或者与DLL库的连接所以,如果在代码⾥要⽤到这些函数那么就要包含头⽂件,编译的时候才能知道这些函数的原形;在进⾏代码连接的时候就需要库⽂件了,这时连接器就把函数的实现代码(静态库)连接到你的程序或者将你的函数调⽤连接到相应的DLL的对应函数(动态库)lib是静态库, 编译的时候代码直接插⼊到你的程序 ,DLL是动态库,编译的时候,只是产⽣⼀些调⽤DLL内代码的导⼊表,真正运⾏的时候是调⽤的DLL内的代码。
总结起来就是,库⽂件通过头⽂件向外导出接⼝。
⽤户通过头⽂件找到库⽂件中函数实现的代码从⽽把这段代码链接到⽤户程序中去。
.a代表传统的静态函数库(也称作归档⽂件:archive).so代表共享函数库⼆、创建静态库⽂件:1.创建源⽂件willku1.c和willku2.c2.编译源⽂件⽣成.o⽂件(将要包含在库⽂件中的⽬标⽂件)gcc -c willku1.c willku2.c =>willku1.o willku2.o3.创建头⽂件ishead.h内容:void willku1(char *);void willku2(int);4.创建应⽤程序app.c(将调⽤willku2.c⽂件)#include "ishead.h"5.编译、测试应⽤程序app.cgcc -c app.cgcc -o app app.o willku2.o./app6.创建并使⽤库⽂件(.a),使⽤ar创建归档⽂件并将⽬标⽂件加进去。
linux静态库与动态库

linux 静态库、共享库一、什么是库本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
由于windows和linux的本质不同,因此二者库的二进制是不兼容的。
Linux操作系统支持的函数库分为静态库和动态库,动态库又称共享库。
Linux 系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。
二、静态函数库、动态函数库A. 这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。
当然这也会称为它的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。
B.这类库德名字一般是libxxx.so,动态库又称共享库;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。
由于函数库没有被整合进你的程序,而是程序运行时动态申请并调用,所以程序的运行环境中必须提供相应的库。
动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减少应用程序的体积。
注意:不管是静态函数库还是动态函数库,都是由*.o目标文件生成。
三、函数库的创建A.静态函数库的创建ar -cr libname.a test1.o test2.oar:静态函数库创建的命令-c :create的意思-r :replace的意思,表示当前插入的模块名已经在库中存在,则替换同名的模块。
如果若干模块中有一个模块在库中不存在,ar显示一个错误信息,并不替换其他同名的模块。
默认的情况下,新的成员增加在库德结尾处。
B.动态函数库的创建gcc -shared -fpic -o libname.so test1.c test2.c-fpic:产生代码位置无关代码-shared :生成共享库四、静态库和动态库的使用案例:add.c#include <stdio.h>int add(int a,int b){return a + b;}sub.c#include <stdio.h>int sub(int a,int b){return a - b;}head.h#ifndef _HEAD_H_#define _HEAD_H_extern int add(int a,int b); extern int sub(int a,int b); #endifmain.c#include <stdio.h>int main(int argc,char *argv[]){int a,b;if(argc < 3){fprintf(stderr,"Usage : %s argv[1] argv[2].\n",argv[0]);return -1;}a = atoi(argv[1]);b = atoi(argv[2]);printf("a + b = %d\n",add(a,b));printf("a - b = %d\n",sub(a,b));return 0;}生成静态库生成动态库:使用生成的生成的库:其中-L 指定函数库查找的位置,注意L后面还有'.',表示在当前目录下查找-l则指定函数库名,其中的lib和.a(.so)省略。
关于静态链接库(Lib)与动态链接库(DLL)

关于静态链接库(Lib)与动态链接库(DLL)静态链接库(Lib)和动态链接库(DLL)的问题困扰了我很长时间,而当中关键的问题是两者有何联系?又有何区别呢?怎么创建?怎么使用?使用的过程中要注意什么?一直想把这个问题总结一下。
在windows下一般可以看到后缀为dll和后缀为lib的文件,但这两种文件可以分为三种库,分别是动态链接库(Dyna mic-Link Libraries),目标库(Object Li braries)和导入库(Import Libra ries),下面一一解释这三种库。
目标库(Object Li braries)目标库又叫静态链接库,是扩展名为.LIB的文件,包括了用户程序要用到的各种函数。
它在用户程序进行链接时,“静态链接”到可执行程序文件当中。
例如,在V C++中最常使用到的C运行时目标库文件就是LIB C.LIB。
在链接应用程序时常使用所谓“静态链接”的方法,即将各个目标文件(.obj)、运行时函数库(.lib)以及已编译的资源文件(.res)链接到一起,形成一个可执行文件(.exe)。
使用静态链接时,可执行文件需要使用的各种函数和资源都已包含到文件中。
这样做的缺点是对于多个程序都使用的相同函数和资源要重复链接到exe文件中,使程序变大、占用内存增加。
导入库(I mport Li braries)导入库是一种特殊形式的目标库文件形式。
和目标库文件一样,导入库文件的扩展名也是.LIB,也是在用户程序被链接时,被“静态链接”到可执行文件当中。
但是不同的是,导入库文件中并不包含有程序代码。
相应的,它包含了相关的链接信息,帮助应用程序在可执行文件中建立起正确的对应于动态链接库的重定向表。
比如KERNEL32.LIB、USER32.LIB和GDI32.LIB就是我们常用到的导入库,通过它们,我们就可以调用Windows提供的函数了。
如果我们在程序中使用到了Rec tangle这个函数,GDI32.LIB就可以告诉链接器,这个函数在GDI32.DLL动态链接库文件中。
lib静态库与动态库

先删除 除.c和.h外的 所有文件,恢复成我们刚刚编辑完举例程序状态。
# rm -f hello hello.o /usr/lib/libmyhello.so
# ls
hello.c hello.h main.c
#
在来创建静态库文件libmyhello.a和动态库文件libmyhello.so。
#
我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。
# rm libmyhello.a
rm: remove regular file `libmyhello.a'? y
# ./hello
Hello everyone!
#
程序照常运行,静态库中的公用函数已经连接到目标文件中了。
7.可执行程序在执行的时候如何定位共享库文件
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径
此时就需要系统动态载入器(dynamic linker/loader)
对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录找到库文件后将其载入内存
# mv libmyhello.so /usr/lib
# ./hello
./hello: error while loading shared libraries: /usr/lib/libhello.so: cannot restore segment prot after reloc: Permission denied
1.什么是库
在windows平台和linux平台下都大量存在着库。
动态库&静态库

}
return 0;
}
end====================================================
下面是测试程序的 makefile
begin====================================================
//声明函数
int w_log(char *str);
#endif
end=====================================================
下面是all.h 中w_log 函数的实现
begin=====================================================
1)$gcc -fPIC -o libtest.o -c lib_test.c
2)$gcc -shared -o libtest.so libtest.o
也可以直接使用一条命令gcc -fPIC -shared -o libtest.so lib_test.c
动态库调用方式一:
下面就是静态调用刚才生成的 libcommonso.so 动态库了
以下是测试程序:
begin=====================================================
//./test.c
int main(int argc, char *argv[])
4) 使用静态链接库
$nm libtest.a //nm工具可以打印出库中的涉及到的所有符号,库既可以是静态的也可以是动态的。nm列出的符号有很多, 常见的有三种,一种是在库中被
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
静态库与动态库的基础知识手册
相信学过计算机的同学知道静态库和共享库(动态库)这两个词吧!接下来我们一起来回顾一下吧!
C语言的错误处理
环境变量在程序中的处理(环境表)
由于项目比较复杂,代码数量非常庞大,可以把代码打包成库文件,提供库文件和头文件即可。
库文件分成两种:
静态库和共享库(动态库),静态库和共享库都是代码的归档文件。
在使用静态库时,把静态库复制到目标文件中,导致目标文件比较大;使用共享库时,把函数的地址放到目标文件中。
静态库和共享库的优缺点:
静态库的优点:目标文件是独立于库文件,运行速度稍快。
缺点:目标文件太大,不利于代码的修改,扩展和复用共享库的优点:目标文件比较小,修改,扩展和复用比较方便。
缺点:目标文件必须和共享库文件同时存在,代码才能正常运行。
运行速度
稍慢。
开发多半使用共享库。
使用了静态库的步骤:
一.创建静态库文件(.a)
1写源程序add.c保存退出
2编译源文件,得到.o文件(gcc -c)
3创建静态库文件:
ar -r libXX.a add.o //把add.o文件加入到libxx.a库中
注:lib 开头.a结束是静态库的命名规范,XX叫库名
创建静态库文件后,还需要提供.h文件。
二.使用静态库
1写调用源程序text.c ,保存退出
2编译text.c ,只编译不连接(gcc -c)
3连接text.o 和静态库文件
连接方式有三种:
A直接连接
gcc text.o libXX.a
B 配置环境变量LIBRARY_PATH,把库文件所在路径放入其中,然后:
gcc text.o -lXX
C gcc text.o -lXX -L所在路径(双L,推荐)
自己总结:
写.c文件(add.c)
编译不连接gcc -c 得到.o 文件(add.o)
创建库文件ar -r libXX.a add.o
写调用的源程序.c 文件(text.c)
编译不连接gcc -c text.c 得到.o文件(text.o)
连接text.o和静态库gcc text.o libXX.a
运行产生的a.out文件
使用共享库的步骤:
一.创建共享库
1写源程序add.c ,保存退出
2编译
gcc -c -fpic add.c (不写-fpic也行)
3生成共享库
gcc -shared add.o -olibXX.so
注:共享库也需要提供头文件
二.使用共享库
和静态库方式一样
注:连接成功后。
需要配置LD_LIBRARY_PATH才能运行成功。
自己总结:
写.c文件(add.c)
编译不连接gcc -c -fpic add.c 得到.o 文件(add.o)
生成共享库gcc -shared add.o -olibXX.so
写调用函数.c 文件(text.c)
编译不连接gcc -c text.c 得到.o文件(text.o)
连接text.o和共享库gcc text.o libXX.so
连接成功后。
需要配置LD_LIBRARY_PATH才能运行成功
export LD_LIBRARY_PATH=.
运行产生的a.out文件
ldd 命令可以查看使用的共享库。
动态调用共享库(动态编程)
代码在运行时才知道调用哪个函数,执行哪一段代码
相关的函数:
dlopen() dlsym() dlclose() 错误处理dlerror()
dlopen:打开共享库文件
dlclose:关闭共享库文件
dlsym:从一个打开的库文件中获得一个函数,返回函数指针
dlopen(参数1,参数2)第一个参数是共享库的文件名,第二个参数是加载方式:
RTLD_LAZY 是延时加载,open 是不加载,使用加载
RTLD_NOW open 文件的同时加载
返回库文件的首地址
错误处理
C程序没有异常,因此错误处理有自己的一套机制:
用返回值的不同体现错误:
1返回指针类型,一般用NULL 代表错误。
2返回int 类型,返回的数据不可能是-1,一般用-1代表错误。
3返回int 类型,但返回数据有可能是-1,用指针取数据,用返回-1代表错误,返回0代表正确。
4如果不需要考虑错误处理,返回值为void 。
以上四种情况都是一般用法(惯例),都有特殊情况。
当然了在学习的过程中,还是要偶一些练习的,实践是检验真理的唯一途径吗。
以下有几道练习:
写四个函数,实现代码和错误处理
1打印传入的字符串(4)
2测试传入字符串的值,如果不是error ,返回ok,如果是error,代表出错,处理函数的错误。
(1)
3返回0到10 的随机数,如果随机数是5,代表出错。
(2)
4求两个整数的最大值,如果想相等,代表出错(3)
C对于错误的处理提供了一个外部全局变量,三个函数:
#include<errno.h >
errno -----错误的编号,不包括错误的信息
strerror()--把错误编号转换成错误信息
perror()---自动找到错误编号并打印对应的错误信息
printf()----”%m”自动打印错误信息
最常用的的错误处理函数就是perror().
perror()允许传入一些附加信息,帮助程序员定位哪里出了错误
errno 是一个全局变量,可以直接使用。
使用方式:
成功不改变值,失败设置值。
不是所有的函数都是用errno 处理错误
环境变量和环境表
所有的环境变量在程序中可以通过环境表获取
环境表是一个全局变量,类型字符指针数组,获取方式:
extern char** environ;
environ 就是环境表的首地址,是全局变量。