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,但是打印比较好的数据,发现数据错了!!坑爹啊,这样的坑更深沉。

测试代码


参考

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

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