【问题标题】:boost::filesystem::current_path() returns empty pathboost::filesystem::current_path() 返回空路径
【发布时间】:2018-09-03 09:37:11
【问题描述】:

我有一个 C++ 程序,我需要当前路径来稍后创建一个文件夹。我的可执行文件的位置是/home/me/foo/bin。这是我运行的:

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

我在 Ubuntu 16.04 上运行,使用与包管理器 Conan 一起安装的 Boost 1.66。

我曾经在不使用柯南的情况下使用以前版本的 Boost(我相信是 1.45)成功运行此程序。 Boost 通常安装在我的机器上。我现在在运行 create_directories( boostPath); 时得到一个核心转储。

两个问题:

  1. 为什么current_path() 不为我提供实际路径,而是返回和空路径?
  2. 即使 current_path() 什么也没返回,为什么即使我使用sudo 运行它,我仍然会有核心转储?我不是简单地在根目录下创建文件夹吗?

编辑:

运行编译的程序,在两行之间有一些上述变量的cout 输出而不是使用调试模式,通常给我以下输出:

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

有时(大约 20% 的时间)会给我以下输出:

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)

编辑 2:

运行conan profile show default 我明白了:

[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]

【问题讨论】:

  • 您确定您没有任何访问(权限)问题吗?
  • @A.Gille,我在使用 VS Code 进行调试时确实有这样的担忧,并使用sudo run 排除它,并在两行之间添加一些cout 以在控制台上打印路径。结果是一样的。
  • sudo run 是指使用sudo 运行编译后的可执行文件吗?尝试直接调用getcwd() 并检查errno 看看可能出了什么问题。
  • 请确保您的conan install 设置与您的构建设置一致。例如,出于向后兼容的原因,默认配置文件(.conan/profiles/defaul 或 conan profile show default)使用 libcxx=libstdc++。但是您的编译器可能默认使用libcxx=libstdc++11。通常这意味着链接错误,而不是运行时,但请检查以防万一。
  • @drodri,成功了!如果您将在答案中详细说明并添加一些解释性行,我将很乐意接受它:)

标签: c++11 boost path boost-filesystem conan


【解决方案1】:

依赖项中使用的libcxx 与您用于构建应用程序的libcxx 之间存在一些差异。

在 g++ (linux) 中,您可以使用 2 种标准库模式,libstdc++,在未启用 C++11 的情况下构建,libstdc++11,在启用 C++11 的情况下构建。当您构建可执行文件(应用程序或共享库)时,链接在一起的所有单独的库必须链接到相同的libcxx

  • libstdc++11 被设为 g++ >= 5 的默认值,但这也取决于 linux 发行版。碰巧的是,即使您在 Ubuntu 14 等较旧的发行版中安装了 g++ >=5,默认的libcxx 仍将是libstdc++,显然要在不中断的情况下升级它并不容易。碰巧在开源中使用的非常流行的 CI 服务,例如 travis-ci,使用的是较旧的 linux 发行版,因此 libstdc++ 链接是最受欢迎的。

  • libstdc++ 是 g++

出于历史和向后兼容性的原因,柯南默认配置文件始终使用libstdc++,即使对于现代发行版中的现代编译器也是如此。您可以在第一次执行柯南时读取您的默认配置文件,也可以在.conan/profiles/default 中找到它作为文件,或使用conan profile show default 显示它。这可能会在柯南 2.0(甚至更快)中发生变化,并且如果可能,将为每个编译器检测到正确的 libcxx

因此,如果您不更改默认配置文件(建议在生产环境中使用您自己的配置文件),那么当您执行conan install 时,安装的依赖项将针对libstdc++ 构建。请注意,在大多数情况下,此 conan install 独立于构建,它只是下载、解压缩和配置所需的依赖项,并使用请求的配置(来自默认配置文件)。

然后,在构建时,如果您不更改 _GLIBCXX_USE_CXX11_ABI,那么您可以使用系统编译器默认值,在本例中为 libstdc++11。在大多数情况下,会出现显示此差异的链接错误。但是在您的情况下,您很不走运,并且您的应用程序设法链接,但随后在运行时崩溃了。

有几种方法可以解决这个问题:

  • 也使用libstdc++ 构建您的应用程序。确保定义_GLIBCXX_USE_CXX11_ABI=0
  • 安装 libstdc++11 的依赖项。编辑您的默认配置文件以使用 libstdc++11,然后发出新的 conan install 并重新构建您的应用。

【讨论】:

  • 解释得很清楚。我现在了解更多在后台发生的事情以及为什么它不起作用。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2010-09-28
  • 2016-01-18
  • 2013-03-28
相关资源
最近更新 更多