首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Folly的共享库引用了Boost中的错误符号?(GCC在OS X上)

为什么Folly的共享库引用了Boost中的错误符号?(GCC在OS X上)
EN

Stack Overflow用户
提问于 2015-11-13 04:19:53
回答 1查看 1.5K关注 0票数 7

我正在尝试构建并运行一个小的示例应用程序,该应用程序在OS上使用Folly,使用GCC 4.9.3。下面是源代码:

代码语言:javascript
复制
#include <folly/AtomicHashMap.h>

int main() {
    folly::AtomicHashMap<int, int> map(256);
    map.insert(std::make_pair(1, 1));
    return 0;
}

我从源代码中构建并安装了Boost (1.59.0)和Folly (最新的GitHub head),确保GCC被使用,现在它们的库和头都可以在/usr/local中使用。GCC和其他依赖项是使用MacPorts安装的。我可以使用以下命令行成功地构建上面的示例:

代码语言:javascript
复制
$ g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib -lfolly -lglog

但是,当我尝试运行它时,会出现以下错误:

代码语言:javascript
复制
$ ./a.out
dyld: Symbol not found: __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs
  Referenced from: /usr/local/lib/libfolly.57.dylib
  Expected in: flat namespace
 in /usr/local/lib/libfolly.57.dylib
Trace/BPT trap: 5

据我所知,它的工作方式是/usr/local/lib/libfolly.57.dylib在加载时通过引用自动提取libboost_program_options.dylib。在运行otool -L时,我可以将其作为依赖项列出

代码语言:javascript
复制
$ otool -L /usr/local/lib/libfolly.57.dylib
/usr/local/lib/libfolly.57.dylib:
    /usr/local/lib/libfolly.57.dylib (compatibility version 58.0.0, current version 58.0.0)
    libboost_context.dylib (compatibility version 0.0.0, current version 0.0.0)
    libboost_program_options.dylib (compatibility version 0.0.0, current version 0.0.0)
    ...

libboost_program_options.dylib位于/usr/local/lib中,如果我将它重命名为其他东西,运行./a.out将导致加载程序抱怨无法找到它("dyld:库未加载: libboost_program_options.dylib")。看来装载机至少能找到它。

我使用nm -gU检查了这个库导出的符号

代码语言:javascript
复制
$ nm -gU /usr/local/lib/libboost_program_options.dylib | grep program_options
    ...
    0000000000023560 T __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
    ...

因此,有一个非常类似的符号,装载机抱怨丢失。这个破损的名字只是有一个不同的后缀。

[编辑:--除非你向右滚动,否则很难看到这些名字,所以它们又出现了:

  • nm说这个库包含__ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
  • 加载时的“缺失符号”是__ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs

我在/usr/local/include/boost/program_options/errors.hpp中找到了相应的声明

代码语言:javascript
复制
namespace boost { namespace program_options {
...
    class BOOST_PROGRAM_OPTIONS_DECL error_with_option_name : public error {
...
    protected:
...
        virtual void substitute_placeholders(const std::string& error_template) const;

我猜想这是Folly在构建它时使用的头文件,因为它是substitute_placeholders在所有/usr/include/usr/local/include/opt/local/include中唯一的匹配出现。(请注意Folly甚至不直接调用这个函数,但是它从folly/experimental/ProgramOptions.h中调用folly/experimental/ProgramOptions.h并使用boost::program_options的其他成员。)

在我看来,名称越长--唯一真正从libboost_program_options.dylib导出的名称--是正确的,因为它包含了std::string参数。

那么,是什么原因导致libfolly.57.dylib引用另一个(较短的)错误名称呢?

其他说明:

  • 我最初从MacPorts安装了Boost,而不是从源代码构建它,这导致了同样的错误。
  • 如果我使用g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib /usr/local/lib/libfolly.a -lglog构建示例--换句话说,只需链接Folly的静态库--问题就会消失,样本就会运行。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-13 05:39:06

使用c++filt (或http://demangler.com)来分解这两个符号,boost库中的符号具有std::__1::basic_string前缀,而愚蠢中缺少的符号具有std::string。一些googling表示,__1子命名空间被libc++ (clang的C++标准库)使用,以避免与libstdc++ (GNU)的冲突。这表明boost是使用clang和libc++编译的,这在OS上是默认的,而愚蠢是用libstdc++编译的(要么使用g++,要么指定不同的标志到clang)。

由于这两个库没有兼容的ABI,所以仅仅修复符号名对您没有帮助,所以您的解决方案必须重新编译,以便它们共享相同的标准库实现。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33685886

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档