Reputation: 9437
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);
}
Upvotes: 7
Views: 2100
Reputation: 9437
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.
Upvotes: 1
Reputation: 94849
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?
g++
and clang++
clang++
code defaults to being built with libc++
you're going to have to have private copies of any c++
libraries if you intend to build them with g++
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++
.
Upvotes: 8