问题:sort的比较函数实现有问题导致进程调用sort时core了。
结论:特别要注意,sort的比较函数必须遵循严格弱排序(strict weak ordering)的规则。
 
这是最近在工作中遇到的一个问题,平时用函数就简单看了函数原型和例子,如无需要,没有去细究太多。结果在sort的使用就碰钉子,今天分享出来,大家也给自己提个醒。不多赘述,直接贴代码。
 
1. std::sort的调用
 
2. 比较函数compareFriUser
 
编译是没问题的,但是运行到这里就会导致core。core的堆栈如下:
 
 
第一次见到这样的core文件,当时第一感觉是怀疑<algorithm>提供的sort的排序算法是不是有问题,当然这么怀疑一个经过历史洗礼的标准库是很蠢的事情。
后面在网上找到了问题所在。
我们所使用的sort原型是这样:
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

手册中对于第三个参数的说明是这样(http://www.cplusplus.com/reference/algorithm/sort/?kw=sort ):

comp
Binary function that accepts two elements in the range as arguments, and returns a value convertible tobool. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.
(翻译:comp是一个接受两个表示范围的元素作为参数的二元函数,它返回一个可转成bool的值。返回值指示了在comp定义的特定的严格弱排序中,第一个参数是否应该排在第二个参数之前。comp函数不会改变任何一个参数,它可以是一个函数指针或一个仿函数。)
 
我们注意到该说明提到了comp参数必须是严格弱排序。网上的一个较好的解读是:严格是说在判断的时候会用"<",而不是"<=",弱排序是因为,一旦"<"成立便认为存在"<"关系,返回ture,而忽略了"="关系和">"区别,把它们归结为false。相关定义可以参阅:http://www.sgi.com/tech/stl/StrictWeakOrdering.html
简单说,在comp中,当参数1和参数2等价时,必须返回false.
在截图中的compareFriUser中,CSGameUser的等价条件是online、hasMsg、m_vip_level都相等,参数1既不小于参数2,参数2也不小于参数1,此时两者等价。
而在中,当p1->m_vip_level == p2->m_vip_level ,却返回了1. 这就违反了严格弱序的定义,会导致不可预估的结果。
在这里,我们只要把这句代码改成p1->m_vip_level > p2->m_vip_level ,问题就解决了。
 
而这样的比较函数之所以会导致sort内部调用core是因为sort内部的排序函数不会进行边界检查,而p1->m_vip_level == p2->m_vip_level 时return true会导致其取到不正确的元素地址。关于这个问题,可参考该链接:http://verihy.me/posts/stdsort-cmp-order/
(该问题可以去仔细研读sort的具体实现)
 
关于以上的问题,在《Effective STL》的条款20和21都有提到,《STL源码剖析》关于sort函数源码也有详细的解读。大家可以去阅读一下。尤其是STL中有很多很好用的函数和数据结构,在没有仔细阅读使用手册的情况下,按照自己的理解去使用它们有时会导致出现不可预估的结果,这个时候参阅这两本书籍和说明文档是十分有用的。

调用sort段错误问题的更多相关文章

  1. libvlc_new 调用产生段错误

    在调试程序的时候,碰到一个奇怪的段错误问题.只要链接的时候使用-Wl,-rpath=./vlc/lib就会产生段错误,如果链接的时候使用的是-Wl,-rpath=../../tool/vlc/lib则 ...

  2. linux C++ 莫名奇异的段错误(segmentation fault),无法调用其他函数

    进来在linux下开发C++项目,遇到了非常奇怪的bug. 项目须要多线程实现,在写好代码后,每当执行到线程函数内部,当内部调用其他函数如printf.fopen等时就会提示段错误(segmentat ...

  3. 【转】段错误调试神器 - Core Dump详解

    from:http://www.embeddedlinux.org.cn/html/jishuzixun/201307/08-2594.html 段错误调试神器 - Core Dump详解 来源:互联 ...

  4. linux下cp覆盖原so文件时引起的段错误原因确定

    原创作品,转载请注明出处http://www.cnblogs.com/leo0000/p/5694416.html 最近因为一个很有意思的段错误学习了一些新的东西. 当时现象是这样的,程序正在运行,系 ...

  5. Linux环境下段错误的产生原因及调试方法小结(转)

    最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且 项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的“段错误”(Segmentation F ...

  6. Linux环境下段错误的产生原因及调试方法小结

    转载自http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基础之 ...

  7. 【转】gdb 调试段错误

    [转]gdb 调试段错误 转自:blog.csdn.net/yangzhu1982/article/details/6318600 开发嵌入式Linux的时候经常会遇到segmentation fau ...

  8. Linux下的段错误(Segmentation fault)

    Linux开发中常见段错误问题原因分析 1 使用非法的内存地址(指针),包括使用未经初始化及已经释放的指针.不存在的地址.受系统保护的地址,只读的地址等,这一类也是最常见和最好解决的段错误问题,使用G ...

  9. strcat函数造成的段错误(Segmentation fault)

    转自:http://book.51cto.com/art/201311/419441.htm 3.21  strcat函数造成的段错误 代码示例 int main() { char dest[7]=& ...

随机推荐

  1. 【BZOJ】2196: [Usaco2011 Mar]Brownie Slicing

    [题意]给定n*m的数字矩阵,要求横着切A-1刀,对每块再分别竖着切B-1刀,是最小子矩阵最大. [算法]二分+贪心 [题解]还记得提高组2015跳石头吗?这道题做法一致,只不过拓展到二维而已. 二分 ...

  2. Creating a new dynamic form project, business modeling.

    The domain logic is like there are a bunch of objects, as well as a lot of configurations, according ...

  3. linux平台学x86汇编语言学习集合帖

    linux平台学x86汇编语言学习集合帖 linux平台学x86汇编(一):https://blog.csdn.net/shallnet/article/details/45543237 linux平 ...

  4. (十五)linux下gdb调试

    一.gdb常用命令: 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或 ...

  5. 在Perl中采用open进行管道操作

    在Perl中采用open进行管道操作 http://blog.sina.com.cn/s/blog_4840fe2a0100b8na.html perl exec管道和子进程 http://blog. ...

  6. Percona XtraDB Cluster(PXC)原理

    Percona XtraDB Cluster(PXC)原理 介绍: PXC曾经属于一套近乎最完美的mysql高可用集群解决方案(现mgr总体上要优于pxc),相比传统的基于主从复制模式的集群架构MHA ...

  7. vim的各种tips

    centos系统,修改vim的配置文件 /etc/vimrc 添加如下内容: 1) 打开 vimrc ,添加以下语句来使得语法高亮显示: syntax on 2) 如果此时语法还是没有高亮显示,那么在 ...

  8. Rsync文件同步服务

    Rsync简介 Rsync是一款开源的.快速的.多功能的.可实现全量及增量的本地或远程数据同步备份的优秀工具,适用于Unix/Linux/Windows等多种操作系统. Rsync的特性 支持拷贝特殊 ...

  9. JDBC数据源连接池(4)---自定义数据源连接池

    [续上文<JDBC数据源连接池(3)---Tomcat集成DBCP>] 我们已经 了解了DBCP,C3P0,以及Tomcat内置的数据源连接池,那么,这些数据源连接池是如何实现的呢?为了究 ...

  10. 从设计图到CSS:rem+viewport+媒体查询+Sass

    根据UI图对移动端的h5页面做样式重构,是前端工程师的本职工作,看似简单,不过想做好却并不容易.下面总结一下其中要点. rem rem是一种相对长度单位,参考的基准是<html>标签定义的 ...