'Attempt to dereference a past-the-end iterator' 对文件系统路径向量进行排序时
'Attempt to dereference a past-the-end iterator' when sorting a vector of filesystem paths
我正在使用 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
}
我在网上看到很多例子,其中 std::sort 是用 vector.end() 调用的。我用 files.end() - 1
试了一下,收到了同样的错误信息。
std::sort
requires a strict weak ordering comparator, as described in [alg.sorting]/p3:
[...] For algorithms other than those described in [alg.binary.search], comp
shall induce a strict weak ordering on the values.
仅当左侧操作数在右侧操作数之前时,严格的弱排序比较器应该 return true
,否则 false
。
std::basic_string::compare
函数将其结果编码为 <0
、0
和 >0
,如果字符串按字典顺序分别小于、等于或大于参数表达式.这允许在单次传递中确定其参数之间的相互关系。但是,正值和负值都可以隐式转换为 true
布尔值,因此结果将被任何标准库算法误解,从而导致未定义的行为。为了避免这种情况,std::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();
// ~^~
}
});
我正在使用 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
}
我在网上看到很多例子,其中 std::sort 是用 vector.end() 调用的。我用 files.end() - 1
试了一下,收到了同样的错误信息。
std::sort
requires a strict weak ordering comparator, as described in [alg.sorting]/p3:
[...] For algorithms other than those described in [alg.binary.search],
comp
shall induce a strict weak ordering on the values.
仅当左侧操作数在右侧操作数之前时,严格的弱排序比较器应该 return true
,否则 false
。
std::basic_string::compare
函数将其结果编码为 <0
、0
和 >0
,如果字符串按字典顺序分别小于、等于或大于参数表达式.这允许在单次传递中确定其参数之间的相互关系。但是,正值和负值都可以隐式转换为 true
布尔值,因此结果将被任何标准库算法误解,从而导致未定义的行为。为了避免这种情况,std::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();
// ~^~
}
});