You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中new[]是否会预留任务管理器未显示的隐形内存?

解答你的内存分配疑问

首先,咱们先拆解你的问题:在VS2017+Win10环境下,执行char* p1 = new char[1073741824];(也就是1GiB的数组分配)时,会不会存在任务管理器/资源监视器没显示的额外内存预留?结合你遇到的bad_alloc错误,我分情况给你讲清楚:

核心前提:32位 vs 64位程序

这是你遇到bad_alloc的关键可能原因,先明确:

  • 如果你的程序是32位:Win10下32位程序默认只有2GiB的用户态虚拟地址空间(就算物理内存有4GB也没用)。你已经分配了2GiB,再尝试分配1GiB,虚拟地址空间直接不够,必然抛出bad_alloc——这种情况下连分配都没成功,自然不存在什么额外内存预留。
  • 如果是64位程序:虚拟地址空间大到几乎用不完,这时候才需要考虑内存分配的细节。

标准new操作的内存行为

在VS2017的CRT(C运行时库)中,对于超过512KB的大内存分配,new会直接调用Windows的VirtualAlloc API,而不是用堆分配。默认情况下,这个调用会同时完成虚拟地址空间的预留(Reserve)和物理内存/分页文件的提交(Commit):

  • 任务管理器的「已提交内存(Commit Size)」会立刻增加1GiB,这部分是会显示的。
  • 「工作集(Working Set)」只有当你实际读写这些内存页时才会逐步增加(因为Win10是按需加载物理内存的),但这不属于“未显示的额外预留”,只是物理内存的延迟分配。

会不会有任务管理器没显示的额外内存?

答案是:标准new操作不会预留请求之外的额外内存,除非有以下特殊情况:

  1. CRT堆的小分配管理开销:但对于1GiB这么大的块,CRT会绕过堆直接用VirtualAlloc,这部分管理内存可以忽略不计,不会影响你的分配结果。
  2. 手动预留未提交的虚拟地址空间:如果你自己调用VirtualAlloc并指定MEM_RESERVE标记,这时候只是占了虚拟地址空间,没有提交物理内存/分页文件,任务管理器的已提交内存不会显示这部分。但标准new不会这么做,它默认是直接提交的。

你遇到bad_alloc的可能原因(64位程序场景)

如果你的程序是64位,那大概率是虚拟地址空间碎片问题:虽然总虚拟地址空间足够,但找不到连续的1GiB地址块来分配数组(数组需要连续的地址空间)。你可以用微软的VMMap工具查看进程的虚拟地址空间分布,就能清楚看到有没有连续的大内存块可用。

几个排查建议

  • 先确认你的项目是64位:VS2017中,右键项目→属性→配置属性→链接器→系统→目标计算机,选择x64而非x86。
  • 用VirtualAlloc手动测试分配:试试直接调用VirtualAlloc(NULL, 1073741824, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE),如果成功,说明是CRT的new有额外限制;如果失败,就是系统层面的问题(比如虚拟地址碎片)。
  • 检查是否有其他内存泄漏:虽然你说预留了4GB物理内存,但如果程序之前分配了很多小内存块导致虚拟地址空间碎片化,也会影响大内存分配。

内容的提问来源于stack exchange,提问作者Jimmy Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:04:10