当前位置:网站首页>C专家编程 第5章 对链接的思考 5.3 函数库链接的5个特殊秘密
C专家编程 第5章 对链接的思考 5.3 函数库链接的5个特殊秘密
2022-08-04 04:44:00 【weixin_客子光阴】
函数库连接的五个特殊秘密:(UNIX链接的真实情况)
1.动态库文件的扩展名“.so”,而静态库文件的扩展名是“.a”
共享archive的文件名扩展名“.sa”,共享archive只是一种过渡形式,帮助人们从静态库转变成动态库。
2.例如,通过-lthread选项,告诉编译链接到libthread.so
实际上,编译器被告知根据选项-lname链接到相应的函数库,函数库的名字是libname.so---换句话说,"lib"部分和文件的扩展名被省略了,但在前面加了一个“-l”。
3.编译器在确定的目录找到库
它查看一些特殊的位置,在/usr/lib中查找库。例如,线程库位于/usr/lib/libthread.so.
编译器选项-Lpathname告知链接器一些其他的目录,如果命令中加入了-l选项,链接器就往这些目录查找函数库。系统中的环境变量LD_LIBRARY_PATH和LD_RUN_PATH用于提供这类信息。处于安全,性能和创建运行独立性方面的考虑,使用环境变量的做法现在已经不提倡。一般还是在链接时使用-Lpathname和-Rpathname选项。
4.观察头文件,确认所使用的函数库
一个很好的建议就是可以观察程序所使用的#include指令。在程序中所包含的每个头文件都可能代表一个必须链接的库。但是头文件的名字通常并不与它所对应的函数库名相似。
Solaris 2x下的库约定
#include文件名 库路径名 所用的编译器选项
<math.h> /usr/lib/libm.so -lm
<math.h> /usr/lib/libm.a -dn -lm
<stdio.h> /usr/lib/libc.so 自动连接
"/user/openwin/include/X11.h" /usr/openwin/lib/libX11.so -L/usr/openwin/lib-1X11
<thread.h> /usr/lib/libthread.h -lthread
<curses.h> /usr/lib/libcurses.a -lcurses
<sys/socket.h> /usr/lib/libsocket.so -lsocket
函数库链接所存在的另一个不一致就是函数库包含许多函数的定义,但这些函数的原型声明
却散布于多个头文件中。
nm命令在/usr/lib的每个函数库中浏览所有的符号,从中寻找所丢失的符号。在缺省情况下,链接器会在/usr/cc/lib和/usr/lib中查找,你也应该从这两个地方着手,如果找不到就进一步扩展查找范围。(如/usr/openwin/lib)
%cd /usr/lib
%foreach i (lib?*)
?echo $i
?nm $i | grep xdr_refrence | grep -v UNDEF
?end
...
这会在该目录中的所有函数库上运行nm命令,它显示函数库中已知的符号列表。通过grep设定需要搜索的符号,并过滤标记为UNDEF符号(在该函数库中有引用,但不是在此处定义)。结果显示xdr_reference位于libnsl库。需要在编译器命令行的末尾加上-lnsl。
5.与提取动态库中的符号相比,静态库中的符号提取的方法限制更严
在动态链接中,所有的库符号进入输出文件的虚拟地址空间中,所有的符号对于链接在一起的所有文件都是可见的。相反,对于静态链接,在处理archive时,它只是在archive中查找载入器当时所知道的未定义符号。简而言之,在编译器命令行中各个静态链接库出现的顺序是非常重要的。符号是通过从左到右的顺序进行解析的。如果相同的符号在两个不同的函数库中有不同的定义,且静态库出现的顺序不同,其结果就有可能不同。
如果在自己的代码之前引入了静态库,又会带来一个问题。因为此时尚未出现未定义的符号,所以它不会从函数库中提取任何符号。接着,当目标问题被链接器处理时,他所有的对函数库的引用都将是未实现的!
libm经常是以静态链接的archive形式存在。如果你的程序使用了一些数学函数如sin()等,若像下面这样进行静态链接:
cc -lm main.c
则会得到一条错误信息,如下:
Undefined first referenced
symbol in file
sin main.o
ld:fatal: Symbol referencing errors. No output written to a.out
为了能从math库中提取所需的符号,首先需要让文件包含未解析的引用,如下所示:
cc main.c -lm
链接器采用<命令><文件><选项>这样的约定。
/*函数库选项应置于何处*/
始终将-l函数库选项放在编译命令行的最右边
工作区可以在被载入链接器的模式里声明像下面这样的函数,从而向链接器提供更多的线索:
在PC上,当Borland的编译器驱动器试图猜测需要链接的浮点数时,也会出现这样的问题。
scanf: floating point formats not linked
abnormal program termination(scanf:浮点格式未链接,程序异常中止)
当程序在scanf()或者printf()中使用浮点数格式,但并不调用任何浮点数函数时,就有可能
猜测错误
static void forcefloat(float *p) {
float f = *p; forcefloat(&f);
}
不需要实际调用这个函数,只要保证它被链接即可。这样就能给Borland PC的链接器提供
一个足够可靠的线索,即该浮点数库确实是需要的。
另外还有一条类似的信息,当软件需要数值协处理器而计算机却未安装它时,Microsoft C运行时系统会打印一条信息,表示“浮点数未载入”。可以使用浮点数仿真库重新链接程序来解决这个问题。
边栏推荐
- Converts XML tags to TXT format (voc conversion for yolo convenient training)
- 8.Haproxy 搭建Web集群
- 信息学奥赛一本通 1312:【例3.4】昆虫繁殖
- The Shell function
- 有趣的 Kotlin 0x0E:DeepRecursiveFunction
- [21 Days Learning Challenge] Image rotation problem (two-dimensional array)
- TL431的基本特性以及振荡电路
- 深度学习——以CNN服装图像分类为例,探讨怎样评价神经网络模型
- Basic characteristics of TL431 and oscillator circuit
- if,case,for,while
猜你喜欢
manipulation of file contents
mysql索引笔记
Oracle与Postgresql在PLSQL内事务回滚的重大差异
8. Haproxy builds a web cluster
[Ryerson emotional speaking/singing audiovisual dataset (RAVDESS)]
深度学习——以CNN服装图像分类为例,探讨怎样评价神经网络模型
How to simplify the automation of modern e-procurement?
Converts XML tags to TXT format (voc conversion for yolo convenient training)
day13--postman接口测试
帮助企业实现数字化转型成功的八项指导原则
随机推荐
7. The principle description of LVS load balancing cluster
How to simplify the automation of modern e-procurement?
Eight guiding principles to help businesses achieve digital transformation success
如何动态添加script依赖的脚本
【id类型和NSObject指针 ObjectIve-C中】
数据集类型转换—TFRecords文件
XSS相关知识点
【MD5】采用MD5+盐的加密方式完成注册用户和登录账号
文件系统的简单操作
转:管理是对可能性的热爱,管理者要有闯进未知的勇气
Use serve to build a local server
SQL query String field less than 10 how to check
[Ryerson emotional speaking/singing audiovisual dataset (RAVDESS)]
3000字,一文带你搞懂机器学习!
系统设计.秒杀系统
基于gRPC编写golang简单C2远控
图像处理之Bolb分析(一)
【C语言进阶】程序环境和预处理
【Ryerson情感说话/歌唱视听数据集(RAVDESS) 】
How to dynamically add script dependent scripts