std::sort引发的core

简介:
  1. #include <stdio.h>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <new>
  5. struct foo_t
  6. {
  7.     int size;
  8. };
  9. class cmp_t
  10. {
  11. public:
  12.     bool operator()(foo_t *a, foo_t *b)
  13.     {
  14.         return a->size >= b->size;
  15.     }
  16. };
  17. int main(int argc, char *argv[])
  18. {
  19.     std::vector<foo_t *> vec;
  20.     for (int i = 0; i < 17; i++)
  21.     {
  22.         foo_t *x = new(std::nothrow) foo_t();
  23.         if (NULL == x)
  24.         {
  25.             goto fail;
  26.         }
  27.         else
  28.         {
  29.             x->size = 1;
  30.         }
  31.         vec.push_back(x);
  32.     }
  33.     std::sort(vec.begin(), vec.end(), cmp_t());
  34. fail:
  35.     for(std::vector<foo_t *>::iterator iter = vec.begin(); vec.end(!= iter++iter)
  36.     {
  37.         delete *iter;
  38.         *iter NULL;
  39.     }
  40.     return 0;
  41. }
  42. 然后编译
    1. g++ main.cpp -Werror -Wall -g
    然后执行,此时系统出core,错误类型为段错误
    如果无core文件产生,可以使用
    1. ulimit -c unlimited
    后重新执行一次,此时就会有core文件生成
    然后
    1. gdb a.out core
    2. (gdb) bt
    3. #0  0x0804889e in cmp_t::operator() (this=0xbfed92d0, a=0x0, b=0x9a9d0c8) at main.cpp:16
      #1  0x080497ff in std::__unguarded_partition<__gnu_cxx::__normal_iterator<foo_t**, std::vector<foo_t*, std::allocator<foo_t*> > >, foo_t*, cmp_t> (__first=..., __last=..., __pivot=@0x9a9d1a0, __comp=...) at /usr/include/c++/4.6/bits/stl_algo.h:2233
      #2  0x0804926a in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<foo_t**, std::vector<foo_t*, std::allocator<foo_t*> > >, cmp_t> (__first=..., __last=..., __comp=...) at /usr/include/c++/4.6/bits/stl_algo.h:2265
      #3  0x08048e84 in std::__introsort_loop<__gnu_cxx::__normal_iterator<foo_t**, std::vector<foo_t*, std::allocator<foo_t*> > >, int, cmp_t> (
          __first=..., __last=..., __depth_limit=7, __comp=...) at /usr/include/c++/4.6/bits/stl_algo.h:2306
      #4  0x08048a22 in std::sort<__gnu_cxx::__normal_iterator<foo_t**, std::vector<foo_t*, std::allocator<foo_t*> > >, cmp_t> (__first=..., 
          __last=..., __comp=...) at /usr/include/c++/4.6/bits/stl_algo.h:5368
      #5  0x080487ce in main (argc=1, argv=0xbfed9464) at main.cpp:38

    可以看到,系统core在了排序函数里面。
    然后通过分析stl代码发现以下一段代码
    1. /// This is a helper function...
    2.   template<typename _RandomAccessIteratortypename _Tptypename _Compare>
    3.     _RandomAccessIterator
    4.     __unguarded_partition(_RandomAccessIterator __first,
    5.              _RandomAccessIterator __last,
    6.              const _Tp& __pivot, _Compare __comp)
    7.     {
    8.       while (true)
    9.     {
    10.      while (__comp(*__first, __pivot))
    11.      ++__first;
    12.      --__last;
    13.      while (__comp(__pivot*__last))
    14.      --__last;
    15.      if (!(__first < __last))
    16.      return __first;
    17.      std::iter_swap(__first, __last);
    18.      ++__first;
    19.     }
    20.     }
    此函数完成快速排序中分区功能,即将比哨兵小的数据放在其前,大的放在其后。
    函数中使用的是
    while (__comp(*__first, __pivot))
        ++__first;

    如果当比较元素相同返回真时,此时比较元素将会继续向下遍历,在极端情况下,例如程序中所有元素都是一样的情况下,在这种情况下,就会出现访问越界,结果就是导致程序出现segment fault

    所以在写c++ stl中的比较函数是,bool返回真的时候,一定是“真的”大,或者小,等于的时候只能返回false。


本文转自莫水千流博客园博客,原文链接:http://www.cnblogs.com/zhoug2020/p/4572051.html,如需转载请自行联系原作者
相关文章
|
1月前
|
算法 搜索推荐 C++
【C++】sort()、stable_sort()和partial_sort()排序函数详解
【C++】sort()、stable_sort()和partial_sort()排序函数详解
29 0
|
24天前
|
算法 前端开发 大数据
【C/C++ 基础知识 】C++中易混淆的函数和关键字:std::find vs std::search,std::remove vs std::erase,remove vs delete
【C/C++ 基础知识 】C++中易混淆的函数和关键字:std::find vs std::search,std::remove vs std::erase,remove vs delete
35 0
|
29天前
|
自然语言处理 算法 C++
std::array 教程(来自cppreference.com)
std::array 教程(来自cppreference.com)
22 0
|
7月前
|
开发者
std::tuple还是struct?
std::tuple是C++11提供的新模板类,可以翻译为“元组”,可把多个不同类型的变量组合成一个对象。std::tuple可看做std::pair的泛化实现,std::pair包含两个元素,std::tuple 可以同时包含多个元素,它拥有 struct 的表现,但是无需定义实际的 struct,可用于一个函数返回多个值的场景下。
|
7月前
|
算法 C++ 容器
C++ std::remove/std::remove_if/erase用法探讨
std::remove 不会改变输入vector/string的长度。其过程相当于去除指定的字符,剩余字符往前靠。后面的和原始字符保持一致。
|
8月前
|
存储 容器
2023-3-3-std::array的用法
2023-3-3-std::array的用法
46 0
|
9月前
|
存储 安全 编译器
C++ 中的std::array实现编译器排序
某日二师兄参加XXX科技公司的C++工程师开发岗位第25面: 面试官:array熟悉吗? 二师兄:你说的是原生数组还是std::array? 面试官:你觉得两者有什么区别? 二师兄:区别不是很大,原生数组(非动态数组)和std::array都在栈上开辟空间,初始化的时候需要提供数组长度,且长度不可改变。有一点区别的是,std::array提供了安全的下标访问方法at,当下标越界时会抛出异常。
69 0
|
9月前
|
算法 C++
SGI-STL源码剖析之list::sort()
SGI-STL源码剖析之list::sort()
76 0
解决办法:error: ‘unordered_map’ in namespace ‘std’ does not name a template type
解决办法:error: ‘unordered_map’ in namespace ‘std’ does not name a template type
411 0
|
C++
warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11
136 0