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

C++ C++;符号在共享对象中具有不同的大小,c++,linux,linker,shared-libraries,glload,C++,Linux,Linker,Shared Libraries,Glload,我一直在致力于一个跨平台的窗口库,该库专门用于OpenGL,目前专注于linux。我正在使用glload来管理OpenGL扩展,并且正在将其与我稍后将使用的其他库一起编译成一个.so。正如您所期望的那样,它是动态加载的,但在运行时程序会给出以下输出(手动包装,以便更易于阅读): 现在,很明显,我已经尝试过重新链接,甚至多次重建整个项目(进行测试,而不仅仅是盲目地希望它能神奇地让一切变得更好)。该程序似乎确实愿意运行,因为它将产生一些我所期望的日志输出。我已使用nm确认“符号”在中。因此 nm _

我一直在致力于一个跨平台的窗口库,该库专门用于OpenGL,目前专注于linux。我正在使用glload来管理OpenGL扩展,并且正在将其与我稍后将使用的其他库一起编译成一个
.so
。正如您所期望的那样,它是动态加载的,但在运行时程序会给出以下输出(手动包装,以便更易于阅读):

现在,很明显,我已经尝试过重新链接,甚至多次重建整个项目(进行测试,而不仅仅是盲目地希望它能神奇地让一切变得更好)。该程序似乎确实愿意运行,因为它将产生一些我所期望的日志输出。我已使用
nm
确认“符号”在
中。因此

nm _dist/x64-linux-debug/lib64/libvendor.so | grep glXCreateContextAttribsARB
00000000009e0e78 B glXCreateContextAttribsARB
如果我使用
readelf
查看正在定义的符号,我会得到以下结果(同样,为了格式化,我手动包装了前三行):


恐怕这就是我所能提供的全部帮助,因为我真的不知道该尝试或研究什么。正如我所说,我相信更多的信息将是需要的,所以请说一个我会提供我所能。我正在从我的项目根目录运行这些命令,这让您感到奇怪。

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

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

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

信息类型


查看它的定义位置,然后在gdb中加载共享对象(不运行它),并在那里执行另一个
info-types
,查看它们各自认为它在看什么。如果是同一个问题,请检查预处理器指令。

wilsonmichaelpatrick的答案基本正确,但使用
gdb
可能不是发现问题的最快方法,如果您使用的是非调试版本,则可能根本不起作用

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

readelf -Ws _dist/x64-linux-debug/bin/test _dist/x64-linux-debug/lib64/libvendor.so |
  grep glXCreateContextAttribsARB
这应该显示
测试中定义的符号
libvendor.so
,大小不同

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

最后,使用
-E
-dD
标志对生成上述对象文件的源代码进行预处理,并查看它们之间的区别

更新:

我需要帮助理解它说的话

不要束手无策。阅读
manreadelf
,或者直接手动运行。您将看到如下内容:

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)

这将告诉您所获得的数据的含义。特别是,这告诉您,
test
libvendor.so
中的符号大小是相同的(
8
)。因此,问题不在这两个ELF文件中,而是在其他地方。在其他库上运行
readelf
,并查找大小不同的
glXCreateContextAttribsARB
的定义。然后按照程序的其余部分进行操作。

我遇到了一个与不同大小的对象相关的繁琐问题,因此我想分享我的经验,尽管我很清楚,这只是解释不同对象大小的一个原因,而不是强制要求OP

症状是在调试模式下大小不同的对象,在发布模式下没有。链接器产生了相应的警告。符号名很难破译,但与类模板实例中的一些未命名静态变量有关

原因是调试日志功能a la
LOG(“dosomething”)。LOG宏使用C ANSI宏,该宏扩展到另一个路径,具体取决于头是由应用程序还是由共享库包含。这个字符串就是前面提到的未命名静态变量

更令人厌烦的是,由于我们的make环境,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


我希望这段经历能为你们中的一些人腾出一些时间。

在大多数情况下,您可能只是链接到了错误的库(不同的版本)。例如,您安装了两次
libfoo
,并将可执行文件链接到
-L/path/to/version1-lfoo
,但在运行时,您链接到
/path/to/version2
(您可以通过
ldd yourprogram
看到这一个)

一个原因可能是可执行文件与
-rpath、/path/to/version1
链接,但(与最新版本一样)这会在动态部分设置
运行路径
项;虽然
readelf -Ws _dist/x64-linux-debug/bin/test _dist/x64-linux-debug/lib64/libvendor.so |
  grep glXCreateContextAttribsARB
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)
$ minimal
/home/carlo/minimal: Symbol `_ZN6libcwd8libcw_doE' has different size in shared object, consider re-linking
COREDUMP    : /home/carlo/projects/libcwd/libcwd/elfxx.cc:2381: void libcwd::elfxx::objfile_ct::load_dwarf(): Assertion `size == sizeof(address)' failed.
$ ldd minimal | grep libcwd_r
        libcwd_r.so.5 => /usr/local/install/6.0.0-1ubuntu2/lib/libcwd_r.so.5 (0x00007f0b69840000)

$ echo $LD_LIBRARY_PATH
/usr/local/install/6.0.0-1ubuntu2/lib

$ objdump -a -x minimal | grep PATH
  RUNPATH /opt/gitache/libcwd_r/888f62c44fd64f1486176bf9e35b36f79612790017c31f95e117fc59743a54ca/lib
$ unset LD_LIBRARY_PATH
$ ldd minimal | grep libcwd_r
        libcwd_r.so.5 => /opt/gitache/libcwd_r/888f62c44fd64f1486176bf9e35b36f79612790017c31f95e117fc59743a54ca/lib/libcwd_r.so.5 (0x00007f11d7298000)
$ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-new-dtags")
$ objdump -a -x minimal | grep PATH
  RPATH                /opt/gitache/libcwd_r/888f62c44fd64f1486176bf9e35b36f79612790017c31f95e117fc59743a54ca/lib