std::sort 宕机

本文探讨了一次因std::sort错误导致的宕机问题,详细解析了std::sort的工作原理,包括快速排序、堆排序和插入排序的思想。在调试中发现排序过程中vector被破坏,导致在删除时宕机。std::sort在元素数量超过阈值时使用快速排序,为避免深度过深转而使用堆排序,并最终通过插入排序完成。文章还指出了std::sort的不稳定性,并提出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一次公司项目代码引发了宕机,源于std::sort。相似代码贴在下面。由于std::sort 第三个参数写的不对造成的。

源码:

using Vec = std::vector<std::pair<int, int>>;
void print_elem(const Vec& vec, const std::string& str)
{
    std::stringstream oss;
    for (const auto& item : vec)
    {
        oss << "(" << item.first << "--" << item.second << ")";
    }
    std::cout << str << oss.str() << std::endl;
}
​Vec getVec(uint32_t size)
{
    Vec vec;
    for (uint32_t i = 0; i < size; i++)
    {
        vec.emplace_back(i, rand() % 2 + 1);
    }
    ​ print_elem(vec, "origin: ");
    std::sort(vec.begin(), vec.end(),
              [&vec](const std::pair<int, int>& lhs, const std::pair<int, int>& rhs)
              {
                  print_elem(vec, "sort: ");
                  return lhs.second >= rhs.second;
              });
    ​ return vec;
}
​ int main()
{
    srand(time(NULL));
    const Vec vec = getVec(17);
    return 0;
}

编译:g++ sort.cpp -g -o sort,执行

[cn@sort] ./sort.o 
origin: (0-1)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(8-2)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (0-1)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(8-2)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (0-1)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(8-2)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (8-2)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(0-1)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (8-2)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(0-1)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (8-2)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(0-1)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (8-2)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(0-1)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)
sort: (8-2)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(0-1)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)

......

sort: (15-2)(14-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (15-2)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
sort: (273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)
free(): invalid pointer
已放弃 (核心已转储)

最开始存放的元素是:(0-1)(1-2)(2-2)(3-2)(4-2)(5-1)(6-1)(7-2)(8-2)(9-2)(10-1)(11-1)(12-2)(13-1)(14-2)(15-2)(16-2)

调用std::sort 之后,在中间的过程中出现了非法元素:273-0

(273-0)(15-2)(14-2)(12-2)(9-2)(7-2)(4-2)(3-2)(2-2)(1-2)(8-2)(13-1)(11-1)(10-1)(0-1)(6-1)(5-1)

生成了core文件,使用 gdb调试一下

[c
### 对 `std::list` 进行排序 对于 `std::list` 的排序操作,可以利用标准库提供的算法来完成。由于 `std::list` 不支持随机访问迭代器,因此不能直接使用 `std::sort` 函数对其进行排序。但是可以通过转换成支持随机访问的容器(如 `std::vector`),或者更简单地使用专门针对双向链表设计的排序方法。 一种常见做法是先将列表元素复制到一个临时向量中进行排序后再移回原列表: ```cpp #include <algorithm> #include <list> // 定义要排序的对象类型 typedef int value_type; void sort_list(std::list<value_type>& lst) { // 将列表内容拷贝至向量并调用 std::sort 排序 std::vector<value_type> vec(lst.begin(), lst.end()); std::sort(vec.begin(), vec.end()); // 清空原始列表并将已排序数据重新插入 lst.clear(); lst.assign(vec.begin(), vec.end()); } ``` 另一种更为高效的方法是在不改变原有容器的情况下直接应用 `std::list::sort()` 成员函数来进行就地排序。此成员函数接受可选的自定义比较谓词作为参数,默认情况下按照升序排列元素[^2]。 ```cpp #include <iostream> #include <list> int main() { std::list<int> numbers = {7, 3, 5, 9}; // 使用默认小于运算符 '<' 来排序 numbers.sort(); for (auto num : numbers) std::cout << num << ' '; return 0; } ``` 当需要根据特定条件对 `std::list` 中的内容进行定制化排序时,则可以在调用 `sort()` 方法时提供相应的二元谓词表达式或 lambda 表达式作为第二个参数。 ```cpp #include <functional> #include <iostream> #include <list> struct Person { std::string name; unsigned age; }; bool compare_by_age(const Person& p1, const Person& p2){ return p1.age < p2.age; } int main(){ std::list<Person> people{ {"Alice", 30}, {"Bob", 24}, {"Charlie", 28} }; // 自定义排序规则:按年龄从小到大排序 people.sort(compare_by_age); for(auto&& person : people){ std::cout<<person.name<<" ("<<person.age<<")\n"; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值