【问题标题】:Symbol from shared library not found, though defined未找到来自共享库的符号,但已定义
【发布时间】:2021-11-29 12:59:56
【问题描述】:

我正在编写通过 pybind11 从 Ubuntu 20.04 上的 Python (v3.8) 应用程序调用的 C++ 代码。

运行应用程序出现错误

Traceback (most recent call last):
snip...
ImportError: <full-path>/<lib-name-A>.so: undefined symbol: <mangled symbol name>

ldd on lib-name-A 输出给出了定义符号的 lib B 的绝对路径。库 B 上的 nm -s --demangle 显示符号在文本部分中定义。为了确定起见,我比较了损坏的名称,lib B 中的名称与错误消息中给出的名称相同。

那么,鉴于库存在于 ldd 显示其预期的位置,并且在其中定义了符号,为什么我会收到错误消息?

【问题讨论】:

  • 您确定失败的 Python 应用程序和 ldd 应用程序之间的环境相同吗?例如,变量 LD_LIBRARY_PATH 可能不同?使用 LD_DEBUG=files 是否会显示您失败的 Python 应用程序加载的库是您所期望的?

标签: c++ ubuntu shared-libraries cannot-find-symbol


【解决方案1】:

lib B 上的 nm -s --demangle` 显示符号在文本部分中定义

在 lib B 中定义的函数是必要的,但还不够。该函数还必须从 lib B 中导出

很有可能,事实并非如此。要验证,请运行:

nm -D /path/to/lib-B.so | grep $mangled_symbol_name_here

如果我的猜测是正确的(函数没有导出),你将不会从上面的命令中得到任何输出。

更新:

检查nm -D,发现符号丢失。再次检查-s,符号旁边有t(小写),而不是T

好的,所以我的猜测是正确的。

我在函数声明前添加了__attribute__((visibility("default")))

这是正确的解决方案。

问题是为什么我需要将其明确声明为可见。

很可能是因为您正在使用-fvisibility=hidden 构建此代码,它表示“隐藏所有未明确声明为可见的内容”。

使用-fvisibility=hidden 构建是当前的最佳实践,但您确实需要注意哪些符号在您正在构建的共享库之外使用。

【讨论】:

  • 用 nm -D 检查,符号丢失。再次使用 -s 检查,符号旁边有 t(小写),而不是 T。所以我在函数声明前添加了 __attribute__((visibility("default"))),这解决了问题。该函数不是类成员,而是在预先存在的命名空间中定义的。在我看来,新函数和之前编写的函数之间的唯一区别是使用了 pybind11 类型的参数。问题是为什么我需要将其明确声明为可见。
  • @UriRaz 我已经更新了答案。
猜你喜欢
  • 1970-01-01
  • 2011-02-28
  • 2016-10-16
  • 2018-04-14
  • 2020-01-10
  • 2015-03-08
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多