本文介绍了将std :: filesystem :: path传递给函数segfaults的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试使用std::filesystem::path作为函数参数时,它在我的计算机上出现段错误.这是一个最小的示例:

When I attempt to use std::filesystem::path as a function argument, it segfaults on my machine. Here is a minimal example:

#include <filesystem>

void thing(const std::filesystem::path& p) {
    return;
}

int main() {
    thing("test");
    return 0;
}

此代码段导致gdb的以下回溯:

This snippet results in the following backtrace from gdb:

#0  0x0000563a5a3814b3 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x23, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/stl_vector.h:567
#1  0x0000563a5a38132c in std::filesystem::__cxx11::path::~path (this=0x3, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:208
#2  0x0000563a5a381f74 in std::filesystem::__cxx11::path::_Cmpt::~_Cmpt (this=0x3, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:643
#3  0x0000563a5a381f8f in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt> (__pointer=0x3) at /usr/include/c++/8/bits/stl_construct.h:98
#4  0x0000563a5a381e3f in std::_Destroy_aux<false>::__destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:108
#5  0x0000563a5a381ab0 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:137
#6  0x0000563a5a3817c1 in std::_Destroy<std::filesystem::__cxx11::path::_Cmpt*, std::filesystem::__cxx11::path::_Cmpt> (__first=0x3, __last=0x0) at /usr/include/c++/8/bits/stl_construct.h:206
#7  0x0000563a5a3814c9 in std::vector<std::filesystem::__cxx11::path::_Cmpt, std::allocator<std::filesystem::__cxx11::path::_Cmpt> >::~vector (this=0x7ffd198df8a0 = {...}, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/stl_vector.h:567
#8  0x0000563a5a38132c in std::filesystem::__cxx11::path::~path (this=0x7ffd198df880<error reading variable: Cannot access memory at address 0x2b>, __in_chrg=<optimized out>) at /usr/include/c++/8/bits/fs_path.h:208
#9  0x0000563a5a381247 in main () at /home/user/CLionProjects/test/main.cpp:8
#10 0x00007fd6bb96ab6b in __libc_start_main (main=0x563a5a381200 <main()>, argc=1, argv=0x7ffd198df9b8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffd198df9a8) at ../csu/libc-start.c:308
#11 0x0000563a5a38113a in _start ()

我在Ubuntu 19.10上使用GCC 8.3,我有其他人可以在Windows上编译并运行此代码而没有任何问题,因此它可能是libstdc++

I am using GCC 8.3 on Ubuntu 19.10, I had someone else compile and run this code with no issues on Windows so it could potentially be a bug in libstdc++

推荐答案

我认为问题在于Ubuntu在单个安装中混合了GCC版本.在Ubuntu上,默认的GCC是版本8,但是libstdc++.so.6库来自GCC9.对于GCC 8,std::filesystem定义位于单独的库libstdc++fs.a中,必须明确链接到该库.在GCC 9中,std::filesystem符号位于主libstdc++.so库中.由于安装了Ubuntu,因此libstdc++.so中的GCC 9符号可能会满足由GCC 8编译的代码中未定义的引用,而libstdc++fs.a应满足 的要求.由于GCC 9中的std::filesystem符号与GCC 8中的这些符号的实验版本不兼容,因此它似乎链接正常,但在运行时崩溃.

I think the problem is that Ubuntu mixes GCC versions in a single installation. On Ubuntu the default GCC is version 8, but the libstdc++.so.6 library comes from GCC 9. With GCC 8 the std::filesystem definitions are in a separate library, libstdc++fs.a, which must be linked to explicitly. In GCC 9 the std::filesystem symbols are in the main libstdc++.so library. Because of the mixed up Ubuntu installation it's possible for the GCC 9 symbols in libstdc++.so to satisfy the undefined references in code compiled with GCC 8 which should be satisfied by libstdc++fs.a. Because the std::filesystem symbols in GCC 9 are incompatible with the experimental versions of those symbols in GCC 8, it appears to link OK but crashes at runtime.

如果您确保与-lstdc++fs链接并且确保该选项位于所有目标文件之后,则它应该正确运行,例如这应该工作:

It should work correctly if you make sure you link with -lstdc++fs and make sure that option comes after all your object files, e.g. this should work:

g++ foo.o bar.o -lstdc++fs

但这将有效:

g++ -lstdc++fs foo.o bar.o

应该通过确保-lstdc++fs选项位于所有其他输入文件之后来对Ubuntu gcc-8软件包进行更新以解决此问题.有关更多详细信息,请参见 https://bugs.launchpad.net/ubuntu/+ source/gcc-8/+ bug/1824721

There is supposed to be an update to the Ubuntu gcc-8 packages to fix this, by ensuring the -lstdc++fs option comes after all the other input files. For more details see https://bugs.launchpad.net/ubuntu/+source/gcc-8/+bug/1824721

使用gcc-9进行编译也是可行的,因为使用GCC 9进行编译时,无需链接到-lstdc++fs来使用std::filesystem(对于GCC 9来说,仅需要使用std::experimental::filesystem符号).

Compiling with gcc-9 also works, because when using GCC 9 to compile there is no need to link to -lstdc++fs for std::filesystem (with GCC 9 it's only needed for std::experimental::filesystem symbols).

这篇关于将std :: filesystem :: path传递给函数segfaults的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 13:14