Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

(valid) QFileInfo causes segv when calling QFileInfo::filename() in std::sort



  • I need to sort a list of files based on filename. These files are gathered from a QDirIterator.

    I am using the solution provided here. TL;DR - use std::sort with a QCollator.

    Since QCollator::compare(QString&, QString&) uses strings, I need to get the file path or the filename (or some unique string representation of each file to sort - I need to sort based on filename)

    Problem:

    When sorting, I get the QFileInfo::filename() of each file, and attempt to sort based on this value. However, I reach a point where this causes a segv (see code below). When debugging, in an attempt to find the cause of the problem, (in my specific case) a reports as inaccessible (see second screenshot).

    Code for MVCE:

    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;
    }
    
    //...
    

    What I can say about the file paths is they some may extend to as far as (and possibly further than 180 characters in length, but this is less that the maximum file path length limited by Windows.


    Source of SEGV screenshot
    enter image description here

    Offending line in std::sort screenshot
    enter image description here

    Stack Trace

    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_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>::operator()<QList<QFileInfo>::iterator, QList<QFileInfo>::iterator>(QList<QFileInfo>::iterator, QList<QFileInfo>::iterator) predefined_ops.h 143 0x462e42
    4 std::__unguarded_partition<QList<QFileInfo>::iterator, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>>(QList<QFileInfo>::iterator, QList<QFileInfo>::iterator, QList<QFileInfo>::iterator, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>) stl_algo.h 1902 0x462d2c
    5 std::__unguarded_partition_pivot<QList<QFileInfo>::iterator, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>>(QList<QFileInfo>::iterator, QList<QFileInfo>::iterator, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>) stl_algo.h 1923 0x46198e
    6 std::__introsort_loop<QList<QFileInfo>::iterator, int, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>>(QList<QFileInfo>::iterator, QList<QFileInfo>::iterator, int, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>) stl_algo.h 1952 0x45fed6
    7 std::__sort<QList<QFileInfo>::iterator, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>>(QList<QFileInfo>::iterator, QList<QFileInfo>::iterator, __gnu_cxx::__ops::_Iter_comp_iter<ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>) stl_algo.h 1968 0x45eadd
    8 std::sort<QList<QFileInfo>::iterator, ExplorerDialog::refreshAggregatedFiles()::<lambda()>::<lambda(const QFileInfo&, const QFileInfo&)>>(QList<QFileInfo>::iterator, QList<QFileInfo>::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



  • @CybeX
    Well, the debugger shows a as "<not accessible>", so unless its value has been optimized out that seems to be the cause of the SEGV. I admit I don't know how/why, assuming you only put items into fileInfoImageList via the code you show.

    I would start by just checking you can visit/print out all the QFileInfos in your lists before you start the std::sort()?

    I would also force a complete rebuild just to make sure. The placement of the debug breakpoint on line #319 which is blank looks odd to me, it's not supposed to do that....