连接器重复符号处理(一)动态库重复符号处理规则 您所在的位置:网站首页 motionprootp动态码重复绑定怎么解决 连接器重复符号处理(一)动态库重复符号处理规则

连接器重复符号处理(一)动态库重复符号处理规则

2023-12-20 01:16| 来源: 网络整理| 查看: 265

文章目录 链接静态库时有重复符号动态库链接时处理重复符号的规则符号的优先级 例子可执行程序的二进制文件符号与动态库ABI函数冲突不同动态库ABI符号冲突动态库的内部符号与动态的导出符号重复。

在日常开发工作中,经常会遇到符号重复定义的问题,这篇文章主要描述的是链接器在处理重复符号时的规则。

在解析引用的过程中,最常发生的问题就是会出现重复符号,该问题发生在链接的最后阶段,具体为在所有可用符号列表中包含两个甚至更多同名符号,连接器就会报错,一般如下错误:

./libsecond.a(secondfile.o):在函数‘duplicateFunction(int)’中: /root/test/cf/secondfile.cpp:6: duplicateFunction(int) 的多重定义 ./libfirst.a(firstfile.o):/root/test/cf/firstfile.cpp:6:第一次在此定义

判断相同的符号,在C和C++有些不同:

在C中,只要函数,结构体,数据类型的名称一样,那么就认为这些符号是相同的。在C++中,因为函数重载的存在,只有函数的名称和参数列表中每个参数的类型都相同时函数才是重复的。 链接静态库时有重复符号

下面两个文件 firstfile.cpp和secodfile.cpp分别编译成静态库,再链接到可执行程序中。

void firstFunction(); void duplicateFunction(int a); #include void firsFunction() { std::cout std::cout duplicateFunction(0); secondFunction(); return 0; }

g++ main.cpp -L. -lfirst -lsecond -o app

报错:

./libsecond.a(secondfile.o):在函数‘duplicateFunction(int)’中: /root/test/cf/secondfile.cpp:6: duplicateFunction(int) 的多重定义 ./libfirst.a(firstfile.o):/root/test/cf/firstfile.cpp:6:第一次在此定义

程序app链接libfirst.a和libsecond.a,链接静态库不允许有重复符号。

动态库链接时处理重复符号的规则

链接器在处理动态库的符号链接时,比静态库复杂些,对重复符号并非是零容忍,所以即使多个动态库中有相同的符号,链接器也有一套规则选定一个符号,而非直接报错。 对通过dlopen动态加载的方式并没重复符合的问题。 对静态链接的方式链接动态库处理重复符号为以下规则:

符号的优先级,优先级是根据在进程内存映射中不同部分的符号赋予了不同的重要等级。链接时指定的动态库链接顺序:如果同等优先级的代码中存在两个或多个重复符号,相比于后出现在动态库链接列表中的动态库,更早传递给链接器的动态库中的符号将有更高的优先级。 符号的优先级 第1 优先级符号,客户程序二进制文件符号(链接动态库了的程序)。第2优先级符号,动态库可见符号(动态库导出了的符号)。第3优先级符号,不参与链接的符号(动态库中未导出的符号)。

处理重复符号是通常不考虑静态符号(static方法或变量),无论符号属于客户二进制文件还是属于静态链接的动态库。

例子 可执行程序的二进制文件符号与动态库ABI函数冲突

改例子中包含 一个静态库,一个动态库和客户程序,静态库与动态库中有一个同名的函数。

int staticLibFirstFunction(int x); int staticLibSecondFunction(int x); int sharedStaticDuplicateFunction(int x); #include int staticLibFirstFunction(int x){ std::cout std::cout std::cout std::cout std::cout shlibFunction(); return 0; }

gcc -Wall -g -fPIC -c secondshlib.cpp gcc -shared secondshlib.o -Wl,-soname,libsecondshlib.so.1 -o libsecondshlib.so.1.0.0 ldconfig -n . ln -s libsecondshlib.so.1 libsecondshlib.so

动态库libsecondshlib.so,导出的符号为shlibFunction, secondshlibFunction,secondshlibAnotherFunction。其中shlibFunction为重复符合。

#include #include "firstshlib.h" #include "secondshlib.h" int main() { shlibFunction(); firstshlibFunction(); secondshlibFunction(); secondshlibAnotherFunction(); return 0; }

g++ -Wall -g -I./firstshlib -I./secondshlib -c main.cpp g++ main.o -L./ -lfirstshlib -lsecondshlib -Wl,-R./ -o app

最后生成程序app时,首先链接的是libfirstshlib.so,所以输出结果如下:

firstshlib:shlibFunction firstshlibFunction secondshlibFunction firstshlib:shlibFunction

动态中重复的符号shlibFunction,最终选择的是libfirstshlib.so的符号。 对函数动态库libsecondshlib.so中的函数secondshlibAnotherFunction(),在实现的内部调用的是重复符号shlibFunction(),它最终也是链接的libfirstshlib.so中的符号。

如果将链接顺序改为:g++ main.o -L./ -lsecondshlib -lfirstshlib -Wl,-R./ -o app,输出如下:

secondshlib:shlibFunction firstshlibFunction secondshlibFunction secondshlib:shlibFunction

通过这个例子就可以说明,同优先级的符号,由链接时的顺序决定。

动态库的内部符号与动态的导出符号重复。 void shlibFunction(); void firstshlibFunction(); #include void shlibFunction() { std::cout std::cout shlibFunction(); firstshlibFunction(); secondshlibFunction(); }

g++ -Wall -g -l./fisrtshlib -l./secondshlib -c main.cpp g++ main.o -L./ -lfirstshlib -lsecondshlib -Wl,-R./ -o app

运行app,输出入下:

firstshlib:shlibFunction firstshlibFunction secondshlib,static function:shlibFunction

可执行程序app中的shlibFunction方法是链接的firstshlib中的方法,而secondshlibFunction中调用的shlibFunction链接的是libsecondshlib.so中的自己的内部方法,其实在生成libsecondshlib.so动态库时就确定了。在生成执行文件时,内部符号并不参与链接。

上面就是连接器链接动态库时,处理重复符号的规则,这套规则虽然能避免链接出错,但也可能会导致链接了错误的同名符号而导致逻辑的问题。 一般在开发阶段,应该尽可能的采用独立的命名规则来规避符合重复的问题,特别是在C++中通过命名空间的机制,可以很大程度的避免重复符号。但是对规模庞大,依赖第三方库的应用来说,重复符号的问题难以控制。那么就需要我们能知道这套规则,尽可能的使链接器能链接到正确的符号。

在下一篇文章中,将介绍这套规则可能会导致的问题及解决方法。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有