问题
I am getting consistent segfaults with almost any operation I am trying to perform with boost path.
(Edit: It appears that all segfaulting functions are related to 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;
}
The above is just an example, the following also segfault:auto p = current_path(err);
And:auto p = initial_path(err);
Compiled with:g++-4.9 -lboost_filesystem -lboost_system -std=c++11 main.cpp -o ./path-test
Output:
hello/../world
Segmentation fault: 11
Both GCC and Boost installed via Homebrew.
System specs:
OSX: 10.9.4
GCC: 4.9.1
Boost: 1.0.55_2
Edit:
Compiled with -g
and installed a signal handler as per comment, output:
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 signal handler (Taken from 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:
You're mixing implementations of the C++ standard library.
Boost, when installed via brew will be compiled using clang++
. This toolchain uses libc++
by default.
g++
insists on using it's own libstdc++
implementation.
These implementations are not binary compatible, which is where the problems are arising.
I extracted a fresh copy of boost into a subdirectory, did a:
$ ./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
Then built-it (static only; there's a build issue where it can't make the dynamic libraries in this situation under OSX - ld complains that the -h
option is not supported):
$ ./b2 --layout=tagged threading=multi link=static toolset=gcc-4.8
When I compiled your code (because of threading=multi, I had to add -mt to the link options):
$ 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
$
i.e. it worked just fine in this case.
What does this mean?
- C++ libraries on OSX are a complete PITA if you're trying to mix
g++
andclang++
- because all
clang++
code defaults to being built withlibc++
you're going to have to have private copies of anyc++
libraries if you intend to build them withg++
- homebrew is just following orders when it compiles with
clang++
It's a mess, but if you stick to the <sarcasm>one true compiler</sarcasm>, then you'll be fine. TBH I prefer clang's error messages and the static analysis is excellent; but if you have to use g++
, you'll have to keep private copies of any c++
libraries that you want to use, also compiled with g++
.
回答2:
In addition to Petesh excellent answer, for anyone struggling with building boost using gcc via homebrew:
brew install boost --build-from-source --env=superenv --cc=gcc-<Your GCC version>
Note the --env=superenv
switch, which is a recent addition to Homebrew, so make sure your brew is up to date!
If you are running into issues and aren't sure if boost was compiled with gcc or clang, use otool -L
on any boost dynamic library (.dylib
file) and look for the libc++
or libstdc++
entry.
For example, running the following command after I finally got it working right:
otool -L /usr/local/lib/libboost_system.dylib
Produces the following output:
/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)
The second entry shows that this boost lib links against GCC's libstd++
. If instead it said /usr/lib/libc++.dylib
, then it is still linked against Apple's clang runtime.
Note that using brew enables all variants (single / multi / static / dynamic) as the formula's maintainers incorporate patches to make sure it compiles successfully on OSX - which may not be the base with vanilla boost.
来源:https://stackoverflow.com/questions/25664100/c-all-boost-path-operations-segfault-osx-gcc