C++符号在共享对象中具有不同的大小

the*_*man 7 c++ linux linker shared-libraries glload

我一直致力于一个跨平台窗口库,旨在专门用于OpenGL,目前专注于Linux.我正在利用glload来管理OpenGL扩展,并且正在编译它,以及我稍后将使用的其他库.so.这个`.so正在按照您的预期动态加载,但在运行时程序提供以下输出(手动包装,以便更容易阅读):

_dist/x64-linux-debug/bin/test: Symbol `glXCreateContextAttribsARB' has \
different size in shared object, consider re-linking
Run Code Online (Sandbox Code Playgroud)

现在,显然我已经尝试重新连接,甚至多次重建整个项目(测试出来的东西,而不是盲目地希望它会神奇地使它变得更好).该程序似乎确实愿意运行,因为它会产生一些日志输出,正如我所期望的那样.我曾经nm确认过'符号'在.so

nm _dist/x64-linux-debug/lib64/libvendor.so | grep glXCreateContextAttribsARB
00000000009e0e78 B glXCreateContextAttribsARB
Run Code Online (Sandbox Code Playgroud)

如果我readelf用来查看正在定义的符号,我得到以下内容(同样,为了格式化,我手动包装了前三行):

readelf -Ws _dist/x64-linux-debug/bin/test \
_dist/x64-linux-debug/lib64/libvendor.so | \
grep glXCreateContextAttribsARB
   348: 000000000062b318  8 OBJECT  GLOBAL DEFAULT  26 glXCreateContextAttribsARB
   421: 000000000062b318  8 OBJECT  GLOBAL DEFAULT  26 glXCreateContextAttribsARB
  1370: 00000000009e0e78  8 OBJECT  GLOBAL DEFAULT  25 glXCreateContextAttribsARB
 17464: 00000000009e0e78  8 OBJECT  GLOBAL DEFAULT  25 glXCreateContextAttribsARB
Run Code Online (Sandbox Code Playgroud)

我担心这是我能提供的所有帮助,因为我真的不知道该尝试或研究什么.就像我说的那样,我相信会有更多的信息需要,所以请说一下我会尽我所能.我从我的项目根运行这些命令,包括你想知道.

Emp*_*ian 6

wilsonmichaelpatrick的答案大多是正确的,但使用gdb可能不是找到问题的最快方法,如果你有非调试版本,它可能根本不起作用.

首先,您应该确认实际上存在问题:

readelf -Ws _dist/x64-linux-debug/bin/test _dist/x64-linux-debug/lib64/libvendor.so |
  grep glXCreateContextAttribsARB
Run Code Online (Sandbox Code Playgroud)

这应该显示在test和中定义的符号,并且libvendor.so具有不同的大小.

其次,重新连接test,并libvendor.so-Wl,-y,glXCreateContextAttribsARB标志.这将告诉您哪些对象文件(或库)提供(不同的)定义.

最后,使用-E-dD标记预处理生成上述目标文件的源,并查看它们之间的不同之处.

更新:

我需要帮助消化它说的话

不要无助.阅读man readelf,或只是手动运行.你会看到这样的事情:

readelf -Ws /bin/date | head -5

Symbol table '.dynsym' contains 75 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __ctype_toupper_loc@GLIBC_2.3 (2)
Run Code Online (Sandbox Code Playgroud)

这告诉您所获数据的含义.特别是,这告诉您in test和in 中的符号大小libvendor.so是相同的(8).因此,问题在于这两个ELF文件,而在于其他地方.readelf其他库上运行,并查找glXCreateContextAttribsARB具有不同大小的定义.然后按照剩下的步骤进行操作.


小智 4

运行时注意到在共享对象中编译的 glXCreateContextAttribsARB 和在主程序(甚至可能是先前链接的其他共享对象)中编译的 glXCreateContextAttribsARB 具有不同的大小。这意味着,在共享对象和引用该对象的任何其他内容的单独构建中,它们必须查看定义此对象的不同代码(可能在共享对象中)。有时发生这种情况是因为他们正在查看不同的文件,有时发生这种情况是因为不同的 #define 导致对同一文件的不同解释。无论什么原因,您绝对需要确保在运行时链接在一起的所有内容中以相同的方式定义相同的符号(例如结构)(即使用相同的成员变量和大小)。

它拒绝运行实际上是一件非常好的事情,因为当代码的两个部分在运行时以不同的方式解释同一位内存时,这将是一场灾难。(毫不夸张地说,如果允许这种情况继续下去,任何事情都可能发生。)

您可能想尝试在 gdb 中加载可执行文件(而不运行它)并输入

info types

查看它的定义位置,然后将共享对象加载到 gdb 中(不运行它)并info types在那里执行另一个操作以查看它们每个人认为它正在查看的内容。如果是同样的事情,请检查预处理器指令。