std::sort遇不一致比较(含动态文件系统场景)的行为及安全性
动态文件系统下std::sort结合动态stat比较器的行为分析
问题背景
在对文件列表按修改时间排序时,使用了每次比较都重新调用stat获取文件修改时间的比较器:
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 } };
由于排序过程中文件可能被外部进程修改,会出现A<B、B<C、C<A这类违反严格弱序的比较结果,以下是std::sort在此场景下的行为说明:
核心行为分析
- 崩溃风险:通常不会直接引发崩溃。
stat调用成功时会获取合法的修改时间;即使stat失败(比如文件被删除),未初始化的attribLhs/attribRhs中的st_mtime是随机值,但std::sort本身不会因比较结果异常触发崩溃,仅在极端情况下(如内存访问越界)才可能出现问题,但概率极低。 - 死循环风险:存在死循环的可能性。
std::sort的实现依赖比较器满足严格弱序的规则,一旦比较结果前后矛盾,排序算法的逻辑可能陷入无限循环。不同编译器的std::sort实现对这种非法比较器的容忍度不同,但死循环的风险无法排除。 - 排序错误:必然会出现。由于比较结果动态变化且不一致,最终的排序结果会不符合预期,出现乱序情况,这也是你提到的可接受的情况。
优化建议
若要避免上述风险,建议先批量获取所有文件的修改时间,将文件名与对应的时间缓存到结构体中,再基于静态的结构体列表进行排序。这样比较器使用预先缓存的固定值,能保证严格弱序,不受文件系统动态变化的影响。
内容的提问来源于stack exchange,提问作者SF.
相关产品推荐
相关产品推荐

