C++ vector.resize()程序崩溃且申请容量小于max_size的原因排查
故障原因分析
首先明确前提:vector::max_size()返回的是容器理论上可承载的最大元素数量,仅由地址空间位数决定,不代表系统实际可分配的内存大小,因此申请量小于max_size不代表分配一定能成功。
问题涉及的代码片段如下:
cout<<tp.max_size()<<endl; cout<<2 * nA * B<<endl; cout<<nA<<endl; cout<<B<<endl; tp.resize(B, vector<vector<int>>(nA, vector<int>(2, -1)));
其中tp类型为vector<vector<vector<int>>>,已知参数:max_size = 384307168202282325,nA = 32,B = 100000089。
导致崩溃的可能原因如下:
- 32位程序地址空间限制
如果程序编译为32位版本,用户态可用虚拟地址空间最多仅2~3GB。仅第一层vector需要申请连续内存存储100000089个vector<vector<int>>对象(64位环境下每个vector实例占24字节),就需要约2.4GB连续内存,已经触及32位进程的地址空间上限。加上所有int数据的总大小约24GB,远超过32位进程的内存承载能力,直接触发分配失败。 - 整数溢出导致申请量误判
如果nA、B的类型为32位有符号整数,计算2 * nA * B时会发生溢出:100000089 *32 *2 = 6400005696远大于32位有符号int的最大值2147483647,溢出后会被截断为错误的小值,你看到的输出2105038400就是溢出后的结果,实际申请的内存远大于估算值,直接触发内存不足。 - 系统内存资源耗尽
就算是64位程序,本次申请的总内存(含所有int数据+vector管理结构开销)接近27GB,如果当前系统可用物理内存+交换分区的总容量不足,操作系统会拒绝内存分配请求,导致程序崩溃。 - 连续地址块不足
第一层vector的resize操作需要申请一块连续的虚拟地址段存储1亿个vector<vector<int>>实例,约2.4GB。如果进程的虚拟地址空间存在严重碎片化,没有足够大的连续空闲地址块,就算总空闲内存足够,也会分配失败触发崩溃。
内容的提问来源于stack exchange,提问作者ransomware
相关产品推荐
相关产品推荐

