2014-09-04 50 views
7

我正在尝试使用升压路径执行几乎所有操作的一致性段错误。C++:所有升压路径操作segfault(OSX/GCC)

编辑:似乎所有段错误的功能都与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 

GCC和经由自制升压型安装。

系统规格:

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 

段错误信号处理程序(取自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); 
} 
+1

你能告诉我们一个完整的堆栈跟踪吗?先用'-g'构建! – 2014-09-04 11:57:22

回答

8

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

当通过brew安装时,Boost将使用clang++进行编译。该工具链默认使用libc++

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

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

我提取提升的新副本到子目录中,做了:

$ ./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 

当我编译你的代码(因为线程=多,我不得不-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 

$ 

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

这是什么意思?在OSX

  • C++库,如果你想混一个完整的PITA g++clang++
  • ,因为所有clang++代码默认为正在与libc++建造你将不得不有任何c++传抄如果你打算用g++
  • 自制构建它们的库只是奉命行事当它与clang++

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

+0

Dammit我有一种感觉,这是沿着这些线,但无法弄清楚!我从来不知道clang和gcc不是二进制兼容的(因为这个问题并没有问自己通过brew进行了什么增强)。我会尝试通过brew构建一个gcc版本的boost。 – 2014-09-04 15:41:46

+0

当你使用默认的'-stdlib = libC++'时,它是'clang ++'和'g ++',它们不是二进制兼容的。基本的C编译器绝对是二进制兼容的。我建议坚持使用'g ++'编译的boost *的私人副本;因为如果你进行了酿造的升级,并且没有重新调整配方,那么你最终会像以前一样处于相同的位置 – Petesh 2014-09-04 15:42:54

1

除了Petesh出色答卷,任何人通过自制使用gcc与建筑升压挣扎:

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

注意--env=superenv开关,这是一个最近除了自制,所以请确保您的BREW达日期!

如果你碰到问题,不能确定是否提升与海湾合作委员会或铿锵编译,任何提升动态库(.dylib文件)使用otool -L并查找libc++libstdc++条目。

例如,运行以下命令后,我终于得到它工作的权利:

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

产生以下输出:

/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) 

第二项表明,对GCC的libstd++受此提振LIB链接。如果相反,它说/usr/lib/libc++.dylib,那么它仍然与苹果的clang运行时相关联。

请注意,使用brew可以使公式的所有变体(单/多/静态/动态)作为公式的维护人员加入修补程序,以确保它可以在OSX上成功编译 - 这可能不是基于vanilla boost的基础。