为何该C++ vector在noUrls=300,000,000时抛出bad allocation异常?
为何传入参数noUrls=300,000,000时函数会抛出bad allocation异常?
问题代码
#include <string> #include <vector> #include <algorithm> void generateUrls(int noUrls) { std::vector<std::string> urls; urls.resize(noUrls); // 这一步总能成功 std::size_t i = 0; std::string url = "abcdefghijklmnop"; urls[i] = "https://www." + url + ".com/home/index"; i++; while (std::next_permutation(url.begin(), url.end()) && (i < noUrls)) { urls[i] = "https://www." + url + ".com/home/index"; // 异常抛出点 i++; } } int main() { generateUrls(100000000); // 后续处理结果 return 0; }
已知线索
noUrls=300,000,000未触发int溢出,当前平台int最大值为2,147,483,647- 最终生成的vector预估大小约为12GB
- 系统配置:8GB物理内存 + 16GB分页文件,预期会将部分vector存入分页文件
异常原因分析
实际内存需求远超预估
你预估的12GB只是所有字符串的字符数据总大小,但忽略了完整的内存开销:resize(300000000)会先分配存放3亿个std::string对象的内存,每个std::string对象本身(不含字符数据)通常占用24字节左右(包含指针、长度、容量字段),这部分就需要约7.2GB内存。- 每个赋值后的字符串长度为41字符,远超过
std::string的小字符串优化(SSO)阈值(通常16~24字节),因此每个字符串都需要在堆上单独分配字符内存,这部分总大小约12.6GB。 - 两者相加总内存需求接近20GB,再加上系统本身和其他进程占用的内存,剩余可用虚拟内存不足以覆盖这个需求。
内存碎片化导致分配失败
3亿次小内存块(41字节左右)的分配会引发严重的堆内存碎片化。即使系统总虚拟内存剩余量理论上足够,内存管理器也可能无法找到足够的连续内存块来满足分配请求,最终触发bad_alloc异常。resize与赋值的内存阶段差异
urls.resize(noUrls)仅初始化了3亿个空的std::string对象,空字符串利用SSO不需要堆内存,因此这一步内存占用低,能顺利完成。但后续赋值时,每个字符串都要动态分配堆内存,短时间内的大量内存申请会瞬间耗尽可用内存或触发碎片化问题。
内容的提问来源于stack exchange,提问作者Jez
相关产品推荐
相关产品推荐

