C ++:所有增强路径操作段错误(OSX / GCC)

时间:2014-09-04 11:15:43

标签: c++ macos gcc boost boost-filesystem

我正在尝试使用boost路径执行几乎所有操作的段错误。

编辑:似乎所有的segfaulting函数都与current_path()相关)

Sample program:

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>
#include <iostream>

using namespace std;
using namespace boost::filesystem;
using namespace boost::system;


int main(int argc, const char * argv[])
{
    error_code err;
    auto p = path("hello/../world");
    cout << p.string() << endl;
    path c = canonical(p, err);
    cout << c.string() << endl;
}

以上只是一个例子,以下也是段错:
auto p = current_path(err);

和:
auto p = initial_path(err);

编译:
g++-4.9 -lboost_filesystem -lboost_system -std=c++11 main.cpp -o ./path-test

输出:

hello/../world
Segmentation fault: 11

通过 Homebrew 安装GCC和Boost。

系统规格:

OSX:   10.9.4
GCC:   4.9.1
Boost: 1.0.55_2

修改

使用-g编译并根据注释安装了信号处理程序,输出:

hello/../world
Segfault:
0   path-test                           0x000000010ea215b8 _Z7handleri + 28
1   libsystem_platform.dylib            0x00007fff8b9285aa _sigtramp + 26
2   ???                                 0x00007fff67bdf1a1 0x0 + 140734933889441
3   path-test                           0x000000010ea2196d _ZN5boost10filesystem9canonicalERKNS0_4pathERNS_6system10error_codeE + 69
4   path-test                           0x000000010ea21518 main + 138
5   libdyld.dylib                       0x00007fff832c35fd start + 1
6   ???                                 0x0000000000000001 0x0 + 1

Segfault信号处理程序(取自this question):

void handler(int sig)
{
    void *array[10];
    size_t size;

    size = backtrace(array, 10);

    fprintf(stderr, "Segfault:\n");
    backtrace_symbols_fd(array, size, STDERR_FILENO);
    exit(1);
}

2 个答案:

答案 0 :(得分:8)

您正在混合C ++标准库的实现。

通过brew安装的Boost将使用clang++进行编译。默认情况下,此工具链使用libc++

g++坚持使用自己的libstdc++实施。

这些实现不是二进制兼容的,这就是出现问题的地方。

我将一个新的boost副本提取到一个子目录中,做了一个:

$ ./bootstrap.sh --prefix=/usr/local/boost156 cxxflags="-arch i386 -arch x86_64" address-model=32_64 threading=multi macos-version=10.9 toolset=g++-4.8 stage

然后内置它(仅限静态;在OSX下无法在这种情况下制作动态库的构建问题 - ld抱怨不支持-h选项):

$ ./b2 --layout=tagged threading=multi link=static toolset=gcc-4.8

当我编译你的代码时(由于threading = multi,我不得不在链接选项中添加-mt):

$ g++-4.8 -g -std=c++11 -Iboost_1_56_0  -Lboost_1_56_0/stage/lib -lboost_filesystem-mt -lboost_system-mt main.cpp -o ./path-test
$ ./path-test
hello/../world

$

即。在这种情况下它运作得很好。

这是什么意思?

  • 如果您尝试混合g++clang++
  • ,OSX上的C ++库是一个完整的PITA
  • 因为所有clang++代码默认使用libc++构建,如果您打算使用{{1}构建它们,则必须拥有任何c++库的私有副本}
  • homebrew在使用g++
  • 进行编译时只是遵循命令

这是一团糟,但如果你坚持使用&lt; sarcasm&gt; 一个真正的编译器&lt; / sarcasm&gt;,那么你会没事的。 TBH我更喜欢clang的错误信息,静态分析非常好;但如果必须使用clang++,则必须保留要使用的任何g++库的私有副本,并使用c++进行编译。

答案 1 :(得分:1)

除了Petesh的优秀答案,对于任何通过自制软件使用gcc进行构建提升的人来说:

brew install boost --build-from-source --env=superenv --cc=gcc-<Your GCC version>

请注意--env=superenv开关,这是Homebrew的新增内容,因此请确保您的brew是最新的!

如果您遇到问题并且不确定是否使用gcc或clang编译了boost,请在任何boost动态库(otool -L文件)上使用.dylib并查找{{ 1}}或libc++条目。

例如,在我最终使其正常工作后运行以下命令:

libstdc++

产生以下输出:

otool -L /usr/local/lib/libboost_system.dylib

第二个条目显示此升级lib链接到GCC的/usr/local/lib/libboost_system.dylib: /usr/local/lib/libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/local/lib/gcc/x86_64-apple-darwin13.3.0/4.9.1/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.20.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1) /usr/local/Cellar/gcc/4.9.1/lib/gcc/x86_64-apple-darwin13.3.0/4.9.1/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0) 。如果相反它说libstd++,那么它仍然与Apple的clang运行时相关联。

请注意,使用brew可以启用所有变体(单/多/静态/动态),因为公式的维护者包含补丁以确保它在OSX上成功编译 - 这可能不是带有香草增强的基础。