定义相同函数名的两个 linux 共享对象之间的冲突

Posted

技术标签:

【中文标题】定义相同函数名的两个 linux 共享对象之间的冲突【英文标题】:Conflict between two linux shared objects defining the same function name 【发布时间】:2013-07-25 17:12:28 【问题描述】:

我的问题涉及 Python、Qt、PyQt 和其他东西,但问题实际上是关于 Linux 的 ld.so 实际工作原理。

问题

如果一个程序加载了两个不同的共享库,它们都具有相同的入口点名称(即它们都定义了具有相同名称和签名的函数),它如何知道它正在调用哪个版本?

我的问题

我有一个用 C++ 编写的第三方专有 Linux 应用程序(尽管与原始语言无关),它与 Qt3.3 动态链接。该应用程序嵌入了一个 Python 解释器,可用于为其编写脚本。

您甚至可以使用应用程序的嵌入式 python 代替原来的,使用以下命令:

/path/to/the/program/python

它显示以下内容:

Python 2.7.1 (r271:86832, Sep 16 2011, 18:16:32) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

使用 gcc 4.1.2 我已经从源代码构建并安装了 PyQt4,与系统也拥有的 Qt4 库相对。我相信构建是成功的,因为我可以使用以下命令运行一个小型 PyQt4 应用程序:

/path/to/the/program/python mypyqtapp.py

但是,如果我使用其 GUI 加载程序并加载相同的脚本,它会在第一个 PyQt4 调用时崩溃,这是 QApplication 类的实例化。

由于python环境相同,我怀疑可能是Qt3和Qt4之间的某种共享库冲突。但是,strace -e trace=file 命令显示 python 在这两种情况下都在定位和加载正确的 Qt4 库。

所以,我的问题是,如果一个程序加载了两个定义相同函数的共享不同库,它怎么知道它调用了正确的库? linux 加载程序ld.so 是否以某种方式使用文件名或其他内容限定入口点?我怀疑我的问题可能出在那儿,该应用程序最终加载了两个不同的 QApplication 实例,并且调用了错误的实例,但是 ld.so 内部的实际工作原理让我无法理解。

也可能是我的问题是由完全不同的东西引起的。

谢谢。

【问题讨论】:

你试过像 gdb/ddd 这样的调试器吗? 【参考方案1】:

仅在链接(ld)阶段检测到冲突符号,加载程序(ld-linux.so)不检查冲突符号。

当多个库提供重复符号时,使用第一个加载的。

实际上有人可以使用此功能。通过提供 LD_PRELOAD=overwrite.so,overwrite.so 可以覆盖程序所需的任何函数。

【讨论】:

激发这个问题的真正世界问题早已过时,现在已经不复存在。我想如果我要尝试 LD_PRELOAD 解决方案,应用程序只会在不同的点崩溃。我接受这个答案是因为它确实为关于 ld.so 如何工作的具体问题提供了直接答案。谢谢。

以上是关于定义相同函数名的两个 linux 共享对象之间的冲突的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中的类之间共享对象

在两个不同的 Django 项目之间共享模型

在线程之间共享一个类

在场景之间共享游戏对象

mapstruct工具包的使用

将返回对象赋值给函数定义后的函数名的目的