std::sort coredump 说起

@(c++)

core 的原因

c++ 标准库 sort() 默认采用 < 这个 operator 来排序的, 另个一个重载函数增加第三个参数,指定一个比较的函数,函数接受两个参数。
对于基础类型(int,float..),直接调用 sort(start,end) 即可,对于非基础类型的结构体,可以通过重载对象的 < 运算符或者提供一个比较函数。
详见

本文从一个 core 说起 相信很多人在编写使用 sort 都在这个地方翻车,

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

class CompareGreater {
    public:
        bool operator()(const int* left, const int* right)
        {
            return *left >= *right;
        }
};

int main(int argc, char *argv[])
{
    vector<int *> verPInt;
    for (int i = 0; i < 18; i++) { // will coredump
        int *pInt = new int;
        if (pInt == NULL) {
            cout << "new faile" << endl;
            goto final;
        }
        *pInt = 1;
        verPInt.push_back(pInt);
    }
    sort(verPInt.begin(), verPInt.end(), CompareGreater());
    for (vector<int *>::iterator iter = verPInt.begin(); iter != verPInt.end(); ++iter) {
        cout << **iter;
    }
    cout << endl;
final:
    for (vector<int *>::iterator iter = verPInt.begin(); iter != verPInt.end(); ++iter) {
        delete *iter;
        *iter = NULL;
    }
    return 0;
}

gdb 查看堆栈,发现是 core 在比较函数里面。

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055e88121e00c in CompareGreater::operator()(int const*, int const*) ()

上述代码,所有元素值相同,当个数大于等于 16个 的时候就会 coredump,查看说明,core 的原因是 :

<font color=#0099ff size=5>std::sort()在排序时,比较函数对相等的元素应该返回 false!如果返回 true,会导致程序coredump</font>

因为定义 cmp(x,x) 返回 true 不符合 Strict_weak_orderings,标准库算法里面很多都要求满足 Strict_weak_orderings,使用时需要格外注意,避免翻车。
上述例子代码只需修改比较函数中,将 >= 改为 >即可修复。

为什么是元素个数大于等于 16个 呢,从 STL 源码可以发现,由于 std::sort() 的排序分2种,当元素个数 >16 <font color=#0099ff>(_S_threshold = 16)</font> 时选择快速排序,<=16 个则选择插入排序 (对象少时快排性能不理想)。按照快排原理,每次都是遍历所有值和一个中间值比较,小的放左边,大的放右边。从STL源代码可看出,std::sort() 在遍历比较时,是没有加边界保护的。如果比较相等的元素返回真,则在极端情况下 (如所有元素值相等时) __first 会出现访问越界,导致coredump。
STL 源码 : /usr/include/c++/7/bits/stl_algo.h(具体目录)

深层次的坑

写测试代码时候,发现比较元素从 vector<int *> 改为 vector<int>,比较函数同样错误的写为 >=,运行程序并不会 core,但是打印比较好的数据,发现数据错了!!坑爹啊,这样的坑更深沉。

测试代码


参考

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 原文地址:https://blog.csdn.net/bamboolsu/article/details/4645...
    Caiaolun阅读 1,869评论 0 1
  • 【转载】原文地址:std::string详解作者:kieven2008 之所以抛弃char*的字符串而选用C++标...
    VAYY阅读 664评论 0 2
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,657评论 8 265
  • 1)Quick Time Player 2)文件 3)新建音频录制+新建屏幕录制
    亦原阅读 140评论 0 0
  • 成功就是有能力的人做对了选择题,而一个人的价值观决定了你做出的选择,一个个清晰、准确、必要的概念形成的清晰、准确、...
    新自由阅读 324评论 0 0