c++11 - boost::filesystem::current_path() 返回空路径
问题描述
我有一个 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);
。
两个问题:
- 为什么不
current_path()
为我提供实际路径,而是返回和空路径? - 即使 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]
解决方案
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++ < 5 的默认值。
出于历史和向后兼容性的原因,柯南默认配置文件始终使用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
并重建您的应用程序。
推荐阅读
- python - Python 只读取最后一行,但我想要所有的,即使是同名
- database-design - 在 Cassandra 中,如何根据列选择行并稍后更新该列
- php - 负前瞻与预期不匹配
- python - Numpy:使用 .max 更改二维数组中的数字
- php - cURL 错误 77:错误设置证书验证位置:使用 laravel 的 CAfile
- android - Qt Android 应用程序因 UnsatifiedLinkError 而崩溃 - 使用哪个 NDK/SDK?
- string - 有人可以分解这段代码中发生的事情吗?
- kdb - lj 和 ljf 和有什么不一样?
- sql - 在while循环插入语句中通过表获取下一条记录
- java - 如何将 JSON 对象发送到 HTTPRequest 并以 JSON 格式接收响应