当前位置:网站首页>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运行时系统会打印一条信息,表示“浮点数未载入”。可以使用浮点数仿真库重新链接程序来解决这个问题。
边栏推荐
- [21 Days Learning Challenge] Image rotation problem (two-dimensional array)
- 【21 Days Learning Challenge】Direct Insertion Sort
- 深度学习——以CNN服装图像分类为例,探讨怎样评价神经网络模型
- Stop behind.
- 路网编辑器技术预研
- day13--postman接口测试
- 解决问题遇到的问题
- Introduction to the memory model of the JVM
- 有趣的 Kotlin 0x0E:DeepRecursiveFunction
- 8. Haproxy builds a web cluster
猜你喜欢

七夕节,我用代码制作了表白信封

JVM笔记

SQL query String field less than 10 how to check

See how DevExpress enriches chart styles and how it empowers fund companies to innovate their business
![[Ryerson emotional speaking/singing audiovisual dataset (RAVDESS)]](/img/f7/78eea9f14ca97b5e78592c7c2be313.png)
[Ryerson emotional speaking/singing audiovisual dataset (RAVDESS)]

mysql索引笔记

if,case,for,while

Explain detailed explanation and practice

RSS订阅微信公众号初探-feed43

结构体函数练习
随机推荐
拿捏JVM性能优化(自己笔记版本)
ADC噪声全面分析 -03- 利用噪声分析进行实际设计
7-2 LVS+DR Overview and Deployment
JVM的内存模型简介
【机器学习】21天挑战赛学习笔记(一)
Postgresql source code (66) insert on conflict grammar introduction and kernel execution process analysis
mysql索引笔记
42. 接雨水
目标检测-中篇
Postgresql源码(66)insert on conflict语法介绍与内核执行流程解析
软件测试如何系统规划学习呢?
8. Haproxy builds a web cluster
OpenGL绘制一个圆锥
数据集类型转换—TFRecords文件
使用serve搭建本地服务器
帮助企业实现数字化转型成功的八项指导原则
移动支付线上线下支付场景
2022软件测试面试题 最新字节跳动50道真题面试题 刷完已拿下15k 附讲解+答疑
深度学习21天——准备(环境配置)
How to simplify the automation of modern e-procurement?