Linux库在可执行文件中调用含糊不清的命名函数 - 这可能吗?

时间:2017-03-23 18:09:58

标签: linux gcc dynamic-library

我遇到了嵌入式Linux C ++应用程序的问题,我编写了一个由可执行文件和动态链接库组成的应用程序。可执行文件调用一个函数,该函数是库中的入口点之一,但该函数行为异常。我已经使用gdb进行了调查,发现库函数应该在库中调用另一个函数xyz(),它实际上在可执行文件中调用了同名xyz()的函数。

我很惊讶这可能发生,所以也许我做了一些愚蠢的事情。在没有引用可执行文件的情况下,库本身是否链接?如果可执行文件错误地调用了库中的abc()而不是可执行文件中的abc(),这会更有意义,因为它至少与库链接,尽管在这种情况下链接器会发现双重定义?或优先考虑本地功能?

我可以重命名我的函数,因此它们都没有匹配的名称,但我想了解发生了什么。我在这方面没有太多经验,或者使用gcc工具。首先,我认为在上述情况下我甚至可能会发生什么?

可执行文件和库都会调用另一个库。 我使用的库的链接命令是:

powerpc-unknown-linux-gnuspe-g ++ - 4.9.3 aaa.o bbb.o [etc] -shared -o libmylibary.so -L ../otherlibpath -Wl,-rpath-link,.. / otherlibpath -lotherlibname

1 个答案:

答案 0 :(得分:1)

这就是动态链接器的工作方式。可执行文件中的符号优先于动态库中的符号。动态库设计者必须意识到它。她必须采取措施避免不必要的符号不匹配。大多数图书馆使用:

  • 如果C ++使用名称空间。从库导出的所有符号都应该在库名称空间中。
  • 如果是C,请为所有导出的符号使用名称前缀或后缀。例如,OpenSSL库使用前缀SSL_,公共函数的名称类似于SSL_set_mode(),因此避免了不需要的符号冲突。
  • 不要从库中导出应该是私有的符号。如果未从库中导出符号,则动态链接器将使用库中的本地符号。 #pragma visibility是你的朋友。请参阅https://gcc.gnu.org/wiki/Visibility

如果具有重复符号的库是第三方库且其作者未遵循上述建议,则您必须重命名您的函数或者可能要求作者更新库。

修改

导出/不导出可能由#pragma visibility指令(gcc特定扩展名)控制:

void exported_function1(int);
void exported_function2(int);
#pragma GCC visibility push(hidden)
void private_function1(int);
void private_function2(int);
#pragma GCC visibility pop

上面链接的详细信息。