我正在尝试构建并运行一个小的示例应用程序,该应用程序在OS上使用Folly,使用GCC 4.9.3。下面是源代码:
#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安装的。我可以使用以下命令行成功地构建上面的示例:
$ g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib -lfolly -lglog但是,当我尝试运行它时,会出现以下错误:
$ ./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时,我可以将其作为依赖项列出
$ 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检查了这个库导出的符号
$ 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中找到了相应的声明
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引用另一个(较短的)错误名称呢?
其他说明:
g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib /usr/local/lib/libfolly.a -lglog构建示例--换句话说,只需链接Folly的静态库--问题就会消失,样本就会运行。发布于 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,所以仅仅修复符号名对您没有帮助,所以您的解决方案必须重新编译,以便它们共享相同的标准库实现。
https://stackoverflow.com/questions/33685886
复制相似问题