(действительно) QFileInfo вызывает segv при вызове QFileInfo::filename() в std::sort

Мне нужно отсортировать список файлов на основе имени файла. Эти файлы собираются из QDirIterator.

Я использую решение, предоставленное здесь. TL;DR — используйте std::sort с QCollator.

Поскольку QCollator::compare(QString&, QString&) использует строки , мне нужно получить путь к файлу или имя файла (или какое-то уникальное строковое представление каждого файла для сортировки — мне нужно сортировать на основе имени файла)

Проблема:

При сортировке я получаю QFileInfo::filename() каждого файла и пытаюсь сортировать на основе этого значения. Однако я достиг точки, когда это вызывает segv (см. код ниже). При отладке при попытке найти причину проблемы (в моем конкретном случае) a сообщает о недоступности (см. второй скриншот).

Код для MVCE:

// header
QList<QFileInfo> fileInfoImageList, fileInfoVideoList;
QDir dataDirectory; // path that contains folders of various media type

// source
QCollator collator;
collator.setNumericMode(true);
QDirIterator it(dataDirectory.path(), combinedList, QDir::Filter::Files | QDir::Filter::NoDotAndDotDot | QDir::Filter::NoSymLinks, QDirIterator::IteratorFlag::Subdirectories);

while (it.hasNext() && !stopIteratorLoading) {
   QFileInfo fi(it.next());

   if (isImage(fi)) {
        fileInfoImageList.append(fi);
   }
   else if (isVideo(fi)) {
        fileInfoVideoList.append(fi);
   }
}

std::sort(fileInfoImageList.begin(), fileInfoImageList.end(), [&collator](const QFileInfo & a, const QFileInfo & b) {
   QString nameA = a.fileName();     < ------------- offending line causing segv
   QString nameB = b.fileName();
   return collator.compare(nameA, nameB);
});

std::sort(fileInfoVideoList.begin(), fileInfoVideoList.end(), [&collator](const QFileInfo & a, const QFileInfo & b) {
   QString nameA = a.fileName();
   QString nameB = b.fileName();
   return collator.compare(nameA, nameB);
});

if (stopIteratorLoading) {
   return;
}

//...

Что я могу сказать о путях к файлам, так это то, что некоторые из них могут достигать длины (и, возможно, более 180 символов), но это меньше, чем максимальная длина пути к файлу ограничена Windows.


Источник скриншота SEGV введите здесь описание изображения

Оскорбительная строка на std::sort снимке экрана введите здесь описание изображения

Трассировка стека

QFileInfo::filename() возвращает a, поэтому ваш компаратор не подчиняется строгим слабое упорядочение — это эффективная проверка отношения «s1 != s2», а не «s1 ‹ s2». Это неопределенное поведение.


person CybeX    schedule 19.08.2020    source источник
comment
@vahancho смотри обновление   -  person vahancho    schedule 19.08.2020
comment
Спасибо за решение, все работает! Я имел в виду, чтобы проверить, реализовано ли то, что _1_ для своего _2_, но это вылетело из головы. Однако, предполагая реализованный оператор _3_, я бы даже в самом диком воображении не догадался, что это должно было вызвать ошибку segv. Если возможно, не могли бы вы исправить свой ответ, объяснив его?   -  person CybeX    schedule 19.08.2020


Ответы (1)


Попробуйте изменить компаратор сортировки на...

Что такое QCollater::compare(s1, s2)?

std::sort(fileInfoImageList.begin(), fileInfoImageList.end(),
          [&collator](const QFileInfo &a, const QFileInfo &b)
          {
              QString nameA = a.fileName();
              QString nameB = b.fileName();
              return collator.compare(nameA, nameB) < 0;
          });
person G.M.    schedule 19.08.2020
comment
1 QFileInfo::fileName qfileinfo.cpp 758 0x65a1a5a 2 ExplorerDialog::‹lambda()›::‹lambda(const QFileInfo&, const QFileInfo&)›::operator()(const QFileInfo &, const QFileInfo &) const ExplorerView.cpp 309 0x44f30c
3 __gnu_cxx::__ops::_Iter_comp_iterExplorerDialog::refreshAggregatedFiles()::‹lambda()::‹lambda(con st QFileInfo&, const QFileInfo&)››::operator()‹QList::iterator, QList::iterator›(QList::iterator, QList::iterator) predefined_ops.h 143 0x462e42
4 std::__unguarded_partition‹ QList::iterator, __gnu_cxx::__ops::_Iter_comp_iterExplorerDialog::refreshAggregatedFiles()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)›››(QList::iterator, QList::iterator, QList: :iterator, __gnu_cxx::__ops::_Iter_comp_iterExplorerDialog::refreshAggregatedFiles()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)››) stl_algo.h 1902 0x462d2c
5 std:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__unguarded_part:__ QList::iterator, __gnu_cxx::__ops::_Iter_comp_iterExplorerDialog::refreshAggregatedFiles()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)›››(QList::iterator, QList::iterator, __gnu_cxx: :__ops::_Iter_comp_iterExplorerDialog::refreshAggregatedFile s()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)››) stl_algo.h 1923 0x46198e
6 std::__introsort_loop‹QList::iterator, int, __gnu_cxx::__ops: :_Iter_comp_iterExplorerDialog::refreshAggregatedFiles()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)›››(QList::iterator, QList::iterator, int, __gnu_cxx::__ops::_Iter_comp_iterExplorerDialogreg::refreshAgg ()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)››) stl_algo.h 1952 0x45fed6
7 std::__sort‹QList::iterator, __gnu_cxx::__ops::_Iter_comp_iterExplorerDialog: :refreshAggregatedFiles()::‹lambda()::‹lambda(const QFileInfo&, const QFileInfo&)›››(QList::iterator, QList::iterator, __gnu_cxx::__ops::_Iter_comp_iterExplorerDialog::refreshAggregatedFiles()::‹ lambda()::‹lambda(const QFileInfo&, const QFileInfo&)››) stl_algo.h 1968 0x45eadd
8 std::sort‹QList::iterator, ExplorerDialog: :refreshAggregatedFiles()::‹lambda()›::‹lambda(const QFileInfo&, const QFileInfo&)››(QList::iterator, QList::iterator, ExplorerDialog::‹lambda()››::‹lambda(const QFileInfo& , const QFileInfo&)›) stl_algo.h 4868 0x45d9be
9 ExplorerDialog::‹lambda()›::operator()(void) const ExplorerView.cpp 308 0x44f673
10 std::_Function_handler‹void( ), ExplorerDialog::refreshAggregatedFiles()::‹lambda()››::_M_invoke(const std::_Any_data &) std_function.h 316 0x45ec7b
11 std::function‹void ()›::operator()() const std_function.h 706 0x525442 - person CybeX; 19.08.2020