如果比较不一致,std::sort 会怎么做? (A
2024-02-25


我需要按日期对文件列表进行排序。有这个答案 https://stackoverflow.com/questions/7337651/file-sort-in-c-by-modification-time怎么做。但它让我担心:它运行在一个实时文件系统上,该文件系统可以在操作过程中发生变化。

比较函数使用:

struct FileNameModificationDateComparator{
    //Returns true if and only if lhs < rhs
    bool operator() (const std::string& lhs, const std::string& rhs){
        struct stat attribLhs;
        struct stat attribRhs;  //File attribute structs
        stat( lhs.c_str(), &attribLhs);
        stat( rhs.c_str(), &attribRhs); //Get file stats                        
        return attribLhs.st_mtime < attribRhs.st_mtime; //Compare last modification dates
    }
};

据我了解,这个函数可以并且将会针对同一个文件多次调用,并将其与不同的文件进行比较。排序运行时,外部进程可以修改该文件;较旧的文件之一可能会在两次比较之间成为最新的文件,并且会比相当旧的文件更旧,并且会比最新文件之一更新......

什么会std::sort()做?我对结果中的一些罕见的排序错误感到满意。我不喜欢崩溃或冻结(无限循环)或其他类似的不愉快的事情。我安全吗?


正如其他答案已经说过的,交给std::sort不满足比较器弱严格排序要求并在使用相同值多次调用时保留将导致未定义的行为。

这不仅意味着范围最终可能无法正确排序,它实际上可能会导致更严重的问题,不仅在理论上,而且在实践中。正如您已经说过的,一种常见的情况是算法中的无限循环,但它也可能会导致崩溃或漏洞。

例如(我没有检查其他实现是否有类似的行为)我查看了 libstdc++std::sort实现,作为 introsort 的一部分使用插入排序。插入排序调用函数__unguarded_linear_insert, see github镜像 https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_algo.h#L1827。该函数通过比较器对范围执行线性搜索,而不保护范围的末尾,因为调用者应该已经验证搜索的项目将落入该范围。如果调用者中的保护比较和不受保护的线性搜索之间的比较结果发生变化,则迭代器将超出范围递增,这可能会产生堆溢出或 null 取消引用或其他任何情况,具体取决于迭代器类型。

示范见https://godbolt.org/z/8qajYEad7 https://godbolt.org/z/8qajYEad7.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果比较不一致,std::sort 会怎么做? (A

随机推荐