繁体   English   中英

“符号未找到/预期位于:平面名称空间”实际上是什么意思?

[英]What does "Symbol not found / Expected in: flat namespace" actually mean?

当我导入我构建的模块时,出现与 boost-python 相关的错误:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: dlopen(./myMod.so, 2): Symbol not found: __ZN5boost6python7objects15function_objectERKNS1_11py_functionERKSt4pairIPKNS0_6detail7keywordES9_E
  Referenced from: ./myMod.so
  Expected in: flat namespace
 in ./myMod.so

这到底是什么意思? 为什么会出现这个错误?

描述

该问题是由使用libc++编译的对象和使用libstdc++编译的对象混合引起的。

在我们的例子中,该库myMod.so (编译libstdc++ )需要boost-python是编译libstdc++boost-python-libstdc++从现在起)。 boost-pythonboost-python-libstdc++ ,它会正常工作。 否则 - 在它的boost-pythonlibc++ (或另一个 c++ 库)编译的计算机上,加载和运行它会出现问题。

在我们的例子中,发生这种情况是因为libc++开发人员有意更改了他们所有符号的名称,以防止您(并保存您)将来自他们库的代码和来自不同库的代码混合在一起: myMod.so需要一个带参数的函数从类型。 libc++ ,这种类型的名称是std::__1::pair 因此,没有找到这个符号。

要理解为什么混合使用相同 API 的两个版本是不好的,请考虑这种情况:有两个库: FooBar 它们都有一个接受std::string的函数,并将其用于某些目的,但它们使用不同的 C++ 库。 Foo创建的std::string将传递给BarBar会认为这是其 c++ 库的std::string的实例,然后可能会发生不好的事情(它们是完全不同的对象)。

注意:在某些情况下,同一 API 的两个或多个不同版本在程序的完全不同的部分中是没有问题的。 如果它们在它们之间传递这个 API 的对象,就会出现问题。 但是,检查可能非常困难,尤其是当他们仅将 API 对象作为另一个对象的成员传递时。 此外,库的初始化函数可以做不应发生两次的事情。 另一个版本可能会再次做这些事情。

如何解决?

  • 您可以随时重新编译您的库并使它们相互匹配。

  • 您可以将boost-python作为静态库链接到您的库。 然后,它几乎可以在每台计算机上运行(即使是没有安装boost-python )。 在此处查看更多相关信息。

概括

myMod.so需要另一个版本的boost-python ,一个使用特定 C++ 库编译的版本。 因此,它不适用于任何其他版本。

未找到符号表示未找到声明的函数或变量的定义。 当共享对象的头文件与您的程序一起编译时,链接器会将声明的函数和对象的符号添加到您编译的程序中。 当您的程序由操作系统的加载器加载时,符号将被解析,以便加载它们的定义。 只是此时如果缺少实现,加载器会抱怨它找不到定义,因为可能无法解析到库的实际路径,或者库本身没有与实现/源文件一起编译,其中函数或对象的定义驻留。 在 linux 期刊http://www.linuxjournal.com/article/6463上有一篇关于此的好文章。

我遇到了同样的问题。

Expected in: flat namespace

添加链接器标志修复了问题

-lboost_python37

将动态库名称更改为安装在操作系统上的名称。

顺便说一下,我的操作系统是 macOS High Sierra,我使用 brew 来安装boost_python3

在我的情况下,我只是在使用 Cython 编译时未能导入所有必需的源(c++ 文件)。

从“找不到符号”之后的字符串中,您可以了解您缺少哪个库。

这是我学到的东西(osx):

如果这应该可以工作(即它可以在另一台计算机上工作),则您可能遇到了 clang/gcc 问题。 要对此进行调试, otool -l在引发错误的 .so 文件或可疑库(在我的示例中它是 boost-python dylib 文件)上使用otool -l并检查内容。 /System/ 文件夹中的任何内容都是使用 clang 构建的,并且应该使用 gcc 编译器安装在其他地方。 切勿删除 /System 文件夹中的任何内容。

.so文件是动态库(so = 共享对象)。 在 Windows 上,它们被称为.dll (动态链接库)。 它们包含已编译的代码,其中包含可用于链接它们的任何可执行文件的函数。

这里需要注意的重要一点是那些.so不是 Python 文件。 它们可能是从 C 或 C++ 代码编译的,并且包含可以从 Python 代码中使用的公共函数(请参阅关于用 C 或 C++ 扩展 Python 的文档)。

在你的情况下,你有一个损坏的.so 尝试重新安装受影响的库或 Python,或两者。

问题

作为 Rails 应用程序的一部分运行 puma 时,我遇到了同样的问题

LoadError:dlopen(/Users/alucard/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/puma-5.6.4/lib/puma/puma_http11.bundle,0x0009):找不到符号在平面命名空间“_ERR_load_crypto_strings”中

  • /Users/alucard/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/puma-5.6.4/lib/puma/puma_http11.bundle

解决方案

只需再次安装 puma gem 即可解决gem install puma

就我而言,我收到了:

ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/xmlsec.cpython-38-darwin.so, 0x0002): symbol not found in flat namespace '_xmlSecDSigNs'

背景:

M1 MacBook Pro 带蒙特利

我正在使用 python virtualenv(使用 pyenv)来使用早期版本的 python3.8 (3.8.2),而我的系统本机安装了 3.8.10。

当我在激活的 3.8.2 virtualenv 中时,我注意到 dlopen() 中的路径指向本机 python 安装中的包,而不是 virtualenv 安装。

解决方案:

就我而言,我根本不需要原生 3.8 版本,所以我只是将其删除,这解决了问题。

我找到的解决方案之一是使用 no-binary 标志卸载并重新安装它,这会强制 pip 从源代码编译模块,而不是从预编译的 wheel 安装。

pip install --no-binary :all: <name-of-module>

在这里找到这个解决方案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM