深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
来源:互联网 发布:淘宝网唯品会 编辑:程序博客网 时间:2024/06/01 08:00
注意:编译器为gcc,若使用g++,请在库里面加上extern “C”
两个静态库
首先测试静态链接库,大概的代码如下:
liba.c
liba.h
libb.c
libb.h
静态库的生成:
动态库生成:
fpic:表示为位置无关,也即在任何内存位置都可以运行。
可以看到liba和libb都有相同的common函数,但是打印出的内容都是自家的。
下面我们分别生成静态链接库做测试,生成好后,写个主程序进行测试。
编译生成结果如下:
可以得出一个结论:都为静态链接库,有同名函数参与的情况下,链接会出现符号多次定义的错误。
两个动态库
再来看看动态链接库,同样的liba、libb生成动态链接库
测试主程序不修改,还是为:
编译结果和顺序,结果如下:
这种编译方式叫做动态链接库的隐式调用,如果你删除一个liba.so,运行a.out会出现不能找到动态库的错误。
这种情况也可以称为 加载时链接!静态库属于编译时链接!
可以得出第二个结论:若都为动态库,并且进行隐式调用,输出结果和动态库的顺序有关。
再继续看看动态加载动态库。
修改测试程序
编译结果如下所示:
这种情况称为运行时链接。
如果我们再把动态库的名字加上去呢?
同样可以得出结论:动态链接库如果不加库选项,函数调用是正确的,加库路径,会以库的路径顺序为主!左边覆盖右边。而且当只链接一个时也生效。如:
一个静态,一个动态
再来看看一个静态文件和一个动态文件。
修改测试主程序
测试结果如下:
libb为静态链接!liba为动态加载。
输出正常!
再看下如果动态库的库名显示的加载如编译选项中:
结论:在有静态库和动态库时,不把动态库名显示加入编译选项,输出是正常的,如果加进去以静态库为主,和link的顺序无关。
补充:
另外:
这种一个共享对象里面的全局符号被另一个共享对象的全局符号覆盖的现象又被称为共享对象的全局符号介入。
两个静态库
首先测试静态链接库,大概的代码如下:
liba.c
- #include <stdio.h>
- #include <stdlib.h>
- #include "libA.h"
- void libA()
- {
- common();
- }
-
- void common()
- {
- printf("libA common!\n");
- }
- #ifndef __LIBA_H__
- #define __LIBA_H__
-
- void libA();
- void common();
-
- #endif
libb.c
- #include <stdio.h>
- #include <stdlib.h>
- #include "libB.h"
- void libB()
- {
- common();
- }
-
- void common()
- {
- printf("libB common!\n");
- }
- #ifndef __LIBB_H__
- #define __LIBB_H__
-
- void libB();
- void common();
-
- #endif
- gcc -c liba.c
- ar -rs liba.a liba.o
- gcc -c libb.c
- ar -rs libb.a libb.o
- gcc -fpic -shared -o liba.so liba.c
- gcc -fpic -shared-o libb.so libb.c
可以看到liba和libb都有相同的common函数,但是打印出的内容都是自家的。
下面我们分别生成静态链接库做测试,生成好后,写个主程序进行测试。
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dlfcn.h>
-
- int main()
- {
- libA();
- libB();
- return 0;
- }
可以得出一个结论:都为静态链接库,有同名函数参与的情况下,链接会出现符号多次定义的错误。
两个动态库
再来看看动态链接库,同样的liba、libb生成动态链接库
测试主程序不修改,还是为:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dlfcn.h>
-
- int main()
- {
- liba();
- libb();
- return 0;
- }
这种编译方式叫做动态链接库的隐式调用,如果你删除一个liba.so,运行a.out会出现不能找到动态库的错误。
这种情况也可以称为 加载时链接!静态库属于编译时链接!
可以得出第二个结论:若都为动态库,并且进行隐式调用,输出结果和动态库的顺序有关。
再继续看看动态加载动态库。
修改测试程序
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dlfcn.h>
-
- int main()
- {
- void* handle2 = NULL;
- void (*testLibA)();
- handle2 = dlopen("./libA.so", RTLD_LAZY);
- if (handle2== NULL) {
- perror("error!");
- return ;
- }
- testLibA = dlsym(handle2,"libA");
- if (testLibA== NULL) {
- perror("error!");
- return ;
- }
-
-
- void* handle = NULL;
- void (*testLibB)();
- handle = dlopen("./libB.so", RTLD_LAZY);
- if (handle== NULL) {
- perror("error!");
- return ;
- }
- testLibB = dlsym(handle,"libB");
- if (testLibB== NULL) {
- perror("error!");
- return ;
- }
- testLibA();
- testLibB();
-
- return 0;
- }
这种情况称为运行时链接。
如果我们再把动态库的名字加上去呢?
同样可以得出结论:动态链接库如果不加库选项,函数调用是正确的,加库路径,会以库的路径顺序为主!左边覆盖右边。而且当只链接一个时也生效。如:
一个静态,一个动态
再来看看一个静态文件和一个动态文件。
修改测试主程序
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dlfcn.h>
-
- int main()
- {
- void* handle2 = NULL;
- void (*testLibA)();
- handle2 = dlopen("./libA.so", RTLD_LAZY);
- if (handle2== NULL) {
- perror("error!");
- return ;
- }
- testLibA = dlsym(handle2,"libA");
- if (testLibA== NULL) {
- perror("error!");
- return ;
- }
- testLibA();
-
- libB();
- return 0;
- }
libb为静态链接!liba为动态加载。
输出正常!
再看下如果动态库的库名显示的加载如编译选项中:
结论:在有静态库和动态库时,不把动态库名显示加入编译选项,输出是正常的,如果加进去以静态库为主,和link的顺序无关。
补充:
另外:
这种一个共享对象里面的全局符号被另一个共享对象的全局符号覆盖的现象又被称为共享对象的全局符号介入。
关于全局符号介入这个问题,实际上Linux下的动态链接器是这样处理的:它定义了一个规则,那就是当一个符合需要被加入到全局符号表时,如果相同的符号名已经存在,则后加入的忽略。从动态链接器的角度的装载顺序可以看到,它是按广度优先的顺序进行装载的。
原文地址:http://blog.chinaunix.net/uid-26548237-id-3837099.html
0 0
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 静态链接库和动态链接库相同函数覆盖及库调用顺序
- C++函数动态链接库及静态链接
- 调用静态链接库和动态链接库
- 创建和调用动态链接库与静态链接库
- 静态调用动态链接库
- 静态库链接、动态库静态链接和动态链接
- 静态链接库和动态链接库
- 静态链接库和动态链接库
- 静态链接库和动态链接库
- 动态链接库和静态链接库
- 静态链接库和动态链接库
- C#创建Windows Service(Windows 服务)基础教程
- 反射调用android系统级API函数
- Android设计模式系列-组合模式
- Hadoop之命令集合(全)
- Android 模拟器AVD,设置电池状态
- 深析静态链接库和动态链接库相同函数覆盖及库调用顺序问题
- 数据库常用
- Android设计模式—策略模式
- ActionBar之我的记录
- 程序员必须掌握的十种算法---二分查找算法
- iOS开发 -- 耦合 ,target/action设计模式
- linux查看目录占用空间
- 1053. Path of Equal Weight (30)
- C#中的JSON封装与解析