【问题标题】:g++ undefined reference although symbol is present in *.so fileg++ 未定义的引用,尽管 *.so 文件中存在符号
【发布时间】:2017-09-01 13:25:49
【问题描述】:

我发现了许多类似的问题(例如 thisthatthis),但没有一个可以帮助我解决问题。我有一个 *.so 文件(来自gnss-sdr 的核心),如下所示:

$nm libgnss_system_parameters_dyn.so  | c++filt  |grep Gps_Eph

包含符号Gps_Ephemeris::Gps_Ephemeris(),应该是构造函数。

我写了一些最少的代码:

#include <iostream>
#include <core/system_parameters/gps_ephemeris.h>

int main(int argc,const char* argv[])
{
    Gps_Ephemeris ge;
    return 0; 
}

我用来编译的:

g++  main.cpp -std=c++0x -I some_include_path -L some_lib_path -l gnss_system_parameters_dyn`

然后链接器抱怨:

/tmp/ccHCvldG.o: In function `main':
main.cpp:(.text+0x33): undefined reference to `Gps_Ephemeris::Gps_Ephemeris()'
collect2: error: ld returned 1 exit status

我也尝试过cmake,但它生成的行与此相似(它只是在链接之前添加了-rdynamic),它仍然生成完全相同的链接器错误。

请注意,库和我的最小代码都是使用相同的编译器 (g++-5) 编译的,具有完全相同的标志和相同的 c++0x 标准。


Maxim Egorushkin 的回答如下:

nm --demangle --defined-only --extern-only libgnss_system_parameters.so  |grep Gps_Eph

不输出任何东西。但是,符号是在静态库中定义的( *.a 库):

00000000000006b0 T Gps_Ephemeris::Gps_Ephemeris()
00000000000006b0 T Gps_Ephemeris::Gps_Ephemeris()

知道两者都是由cmake生成的,方式如下:

add_library(lib_name SHARED ${sources_etc}) #for the *.so
add_library(lib_name_2 ${sources_etc}) #for the *.a

这些库中包含/定义的符号应该没有区别,对吧?我在add_library 上的cmake 文档中没有注意到任何内容。我错过了什么明显的东西吗?

【问题讨论】:

  • 您说输出包含符号Gps_Ephemeris::Gps_Ephermeris(),但没有显示实际输出。这是相关的,并且会很有用。此外,您显然没有将该符号复制并粘贴到问题中,因为您拼写错误。我不信任这种书面总结,因为如果你是一个可靠的判断者,可以从你的总结中排除什么,你可能不会问这个问题。
  • 感谢您的关注,我已修复。我主要从事高级计算机视觉,所以是的,我觉得没有资格判断必须排除的内容。我会尽快发布输出。
  • 如果不查看源代码,很难说出为什么从相同源构建的 .so 和 .a 会导出不同的符号。可能会涉及到条件编译。
  • main.o 和 libgnss_system_parameters_dyn.so 中的错位符号名称是什么?当 ABI 更改时,G++ 有时会更改名称修饰。也许 libgnss_system_parameters_dyn.so 的编译方式与您编译 main.cpp 的方式不同。尝试g++ -std=c++0x -c main.cpp; nm main.o 并将损坏的名称与库中的名称进行比较。

标签: c++ g++ undefined-reference name-mangling


【解决方案1】:

检查.so 是否导出符号的迂腐正确方法是nm --demangle --dynamic --defined-only --extern-only &lt;lib.so&gt; | grep &lt;symbol&gt;

如果没有--defined-only,您的命令也会显示未定义符号。

如果没有--extern-only,它还会显示带有内部链接的符号,这些符号无法链接。

您似乎需要链接另一个库,因为链接 libgnss_system_parameters_dyn.so 无法解析 Gps_Ephemeris::Gps_Ephermeris()。一个好的开始方式是该库的文档和示例。

【讨论】:

  • 非常感谢!你是对的。但是,这些符号存在于(等效的)静态库中。我在最后用一些信息更新了这个问题。你能看一下吗?
【解决方案2】:

我过去发现这种类型的错误是由于包含文件中缺少正确的extern "C" { ... } 括号引起的。

【讨论】:

  • 您能否详细说明extern "C" 链接如何处理构造函数?
  • 它没有。它们不是 C 的一部分,而是 C++ 的一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-17
相关资源
最近更新 更多