3

我正在使用 std::filesystem 编写一个简单的文件选择器。当前目录的条目存储在向量中。当我尝试使用 std::sort 对向量进行排序时,程序崩溃。

这发生在 Ubuntu 19.04 上的 g++-9 上。该文件使用 -D_GLIBCXX_DEBUG 和 -D_GLIBCXX_DEBUG_PEDANTIC 调试标志编译。

相关代码如下所示:

#include <filesystem>
#include <vector>
#include <algorithm>

namespace fs = std::filesystem;

struct FileBrowser {
    std::vector<fs::path> files;

    FileBrowser() {
        UpdateFiles();
    }

    void UpdateFiles() {
        files.clear();
        for (const auto& entry : fs::directory_iterator(currentPath)) {
            files.push_back(entry.path());
        }


        std::sort(files.begin(), files.end(), [](const auto& lhs, const auto& rhs) {
            if (fs::is_directory(lhs) && !fs::is_directory(rhs)) {
                return 1;
            } else if (fs::is_directory(rhs) && !fs::is_directory(lhs)) {
                return 0;
            } else {
                return lhs.filename().string().compare(rhs.filename().string());
            }
        });
    }
};

错误消息如下所示:

/usr/include/c++/9/debug/safe_iterator.h:294:
In function:
    __gnu_debug::_Safe_iterator<_Iterator, _Sequence, _Category>::reference 
    __gnu_debug::_Safe_iterator<_Iterator, _Sequence, 
    _Category>::operator*() const [with _Iterator = 
    __gnu_cxx::__normal_iterator<std::filesystem::__cxx11::path*, 
    std::__cxx1998::vector<std::filesystem::__cxx11::path, 
    std::allocator<std::filesystem::__cxx11::path> > >; _Sequence = 
    std::__debug::vector<std::filesystem::__cxx11::path>; _Category = 
    std::forward_iterator_tag; __gnu_debug::_Safe_iterator<_Iterator, 
    _Sequence, _Category>::reference = std::filesystem::__cxx11::path&]

Error: attempt to dereference a past-the-end iterator.

Objects involved in the operation:
    iterator "this" @ 0x0x7fff6c67d9d0 {
      type = __gnu_cxx::__normal_iterator<std::filesystem::__cxx11::path*, std::__cxx1998::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> > > (mutable iterator);
      state = past-the-end;
      references sequence with type 'std::__debug::vector<std::filesystem::__cxx11::path, std::allocator<std::filesystem::__cxx11::path> >' @ 0x0x55ca5b4536c0
    }

我在网上看到很多用vector.end() 调用std::sort 的例子。我尝试了它files.end() - 1并收到了相同的错误消息。

4

1 回答 1

6

std::sort需要严格的弱排序比较器,如[alg.sorting]/p3中所述:

[...] 对于 [alg.binary.search] 中描述的算法以外的算法,comp应对值进行严格的弱排序。

true仅当左侧操作数在右侧操作数之前时,严格的弱排序比较器才应返回,false否则。

std::basic_string::compare函数将其结果编码为和<0,如果字符串按字典顺序分别小于、等于或大于参数表达式。这允许在单次传递中确定其参数之间的相互关系。但是,正值和负值都可以隐式转换为布尔值,因此任何标准库算法都会误解结果,从而导致未定义的行为。为了避免这种情况,函数调用可能如下所示:0>0truestd::sort

std::sort(files.begin(), files.end(), [](const auto& lhs, const auto& rhs) {
    if (fs::is_directory(lhs) && !fs::is_directory(rhs)) {
        return true;
    } else if (fs::is_directory(rhs) && !fs::is_directory(lhs)) {
        return false;
    } else {
        return lhs.filename().string() < rhs.filename().string();
        //                            ~^~
    }
});
于 2019-08-03T13:57:35.267 回答