Search code examples
c++11boostpathboost-filesystemconan

boost::filesystem::current_path() returns empty path


I have a C++ program where I need the current path to later create a folder. The location of my executable is, let's say /home/me/foo/bin. This is what I run:

//Here I expect '/home/me/foo/bin/', but get ''
auto currentPath = boost::filesystem::current_path(); 

//Here I expect '/home/me/foo/', but get ''
auto parentPath = currentPath.parent_path();

//Here I expect '/home/me/foo/foo2/', but get 'foo2/'
string subFolder    = "foo2";
string folderPath   = parentPath.string() + "/" + subFolder + "/";

//Here I expect to create '/home/me/foo/foo2/', but get a core dump
boost::filesystem::path boostPath{ folderPath};
boost::filesystem::create_directories( boostPath); 

I am running on Ubuntu 16.04, using Boost 1.66 installed with the package manager Conan.

I used to run this successfully with a previous version of Boost (1.45 I believe) without using Conan. Boost was just normally installed on my machine. I now get a core dump when running create_directories( boostPath);.

Two questions:

  1. Why isn't current_path() providing me with the actual path, and returns and empty path instead?
  2. Even if current_path() returned nothing why would I still have a core dump even if I run it with sudo? Wouldn't I simply create the folder(s) at root?

Edit:

Running the compiled program, having some cout outputs of the above variables in between the lines rather than using debug mode, normally gives me the following output:

currentPath: ""
parentPath: ""
folderPath: /foo2/
Segmentation fault (core dumped)

But sometimes (about 20% of the times) gives me the following output:

currentPath: "/"
parentPath: "/home/me/fooA�[oFw�[oFw@"
folderPath: /home/me/fooA�[oFw�[oFw@/foo2/
terminate called after throwing an instance of 'boost::filesystem::filesystem_error'
  what():  boost::filesystem::create_directories: Invalid argument
Aborted (core dumped)

Edit 2:

Running conan profile show default I get:

[settings]
os=Linux
os_build=Linux
arch=x86_64
arch_build=x86_64
compiler=gcc
compiler.version=5
compiler.libcxx=libstdc++
build_type=Release
[options]
[build_requires]
[env]

Solution

  • There is some discrepance between the libcxx used in the dependencies, and the one that you are using to build your application.

    In g++ (linux) there are 2 standard library modes you can use, libstdc++, built without C++11 enabled, and libstdc++11, built with C++11 enabled. When you are building an executable (application or shared library), all the individual libraries linked together must link with the same libcxx.

    • libstdc++11 was made the default for g++ >= 5, but this also depends on the linux distro. It happens that even if you install a g++ >=5 in older distros like Ubuntu 14, the default libcxx will still be libstdc++, apparently it is not easy to upgrade it without breaking. It also happens that very popular CI services used in open-source, like travis-ci, used older linux distros, and thus libstdc++ linkage was the most popular.

    • libstdc++ was the default for g++ < 5.

    For historical and backwards compatibility reasons, conan default profile always use libstdc++, even for modern compilers in modern distros. You can read your default profile the first time conan is executed, but also find it as a file in .conan/profiles/default, or show it with conan profile show default. This will likely change in conan 2.0 (or even sooner), and the correct libcxx will be detected for each compiler if possible.

    So, if you are not changing the default profile (using your own profiles is recommended for production), then when you execute conan install, the depedencies which are installed are built against libstdc++. Note that this conan install is independent on the build in most cases, it just downloads, unzip and configure the dependencies you want, with the requested configuration (from the default profile).

    Then, when you are building, if you are not changing _GLIBCXX_USE_CXX11_ABI, then you can be using your system compiler default, in this case, libstdc++11. In most cases, a linking error appears that shows this discrepance. But in your case you were unlucky, and your application managed to link, but then crashed at runtime.

    There are a couple of approaches to solve this:

    • Build your application with libstdc++ too. Make sure to define _GLIBCXX_USE_CXX11_ABI=0.
    • Install your dependencies for libstdc++11. Edit your default profile to use libstdc++11, then issue a new conan install and rebuild your app.