首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“AnyCPU”平台目标上的内存分配模式

“AnyCPU”平台目标上的内存分配模式
EN

Stack Overflow用户
提问于 2019-02-05 22:19:29
回答 1查看 789关注 0票数 6

我有意在一个简单的C#程序中泄漏内存,以了解.NET如何管理这个方面。这是使用int[]数组完成的,每个数组的大小为1000万,每100 is就声明一次。数组的元素没有被“触摸”- -就像在赋值-中那样,以避免将数据带到进程的工作集中:

代码语言:javascript
复制
const int BlockSIZE = 10000000;  // 10 million
const int noOfBlocks = 500;
int[][] intArray = new int[noOfBlocks][];

for (int k = 0; k < noOfBlocks; k++) {
    intArray[k] = new int[BlockSIZE];
    Console.WriteLine("Allocated (but not touched) for array {0}: {1} bytes", k, BlockSIZE);
    System.Threading.Thread.Sleep(100);
}

我正在使用VMMap (由构建的工具)来查看内存是如何分配的。该版本是最近发布的版本(3.25,2018年发布),因此它了解托管堆。

Visual 2015被使用在带有8GB内存的x64 Windows 10机器上,用于编译和生成.exe文件。根据项目构建部分中的Platform target设置,可以看到与内存分配方式有关的不同结果,如下所示。

Platform target设置为x86时,提交的内存将增长到接近2GB的标记,然后抛出内存不足的错误。这个值是预期的,因为2GB是x86体系结构上用户虚拟地址空间的限制(我不使用IncreaseUserVA,这可能会使这个值达到3 GB 编辑__:这不是完全正确的-参见下面的答案)。在本例中,VMMap的输出如下。与预期一样,大多数提交的数据都属于托管堆类别。

Platform target设置为x64时,所提交的区域会像预期的那样不断增长。最终,该应用程序需要停止使用,因为它一直在分配内存。这也是意料之中的,因为只要可用的ram +分页文件的总量能够容纳增长,64位Win10框的理论限制是每个用户虚拟地址空间128 TB (受当前处理器的限制,因为它们只使用虚拟地址中可用的64位中的48位)。VMMap的输出低于。同样,大多数已提交的字节属于托管堆类别。

Platform target设置为Any CPU并勾选Prefer 32-bit (这实际上是Visual 2015中的默认设置)时,结果就不那么简单了。首先,当提交的内存达到3.5GB时,抛出内存不足的异常。其次,托管堆中的私有字节仅增长到大约1.2GB,之后私有数据类别将注册下一个分配的数据。下面是VMMap的输出。

为什么分配发生在Any CPU + Prefer 32-bit设置的最后一段中所描述的情况?具体来说,为什么大量的数据列在私有数据下而不是托管堆下?

稍后编辑:添加图片内联,以更好的清晰度。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-05 22:31:07

在Windows64 Windows64 (wow64)下运行的LARGEADDRESSAWARE 32位进程具有4GB的用户模式虚拟地址空间(VAS),因为内核内存是64位,不需要映射到具有32位指针的4GB可寻址地址。而且你不需要用/3GB switch引导Windows就能得到它。

在为X86编译时,您可能希望在32位和64位平台上有相同的行为,因此不设置LARGEADDRESSAWARE标志是有意义的。而且,这可能是由向后兼容性所决定的。在很久以前,一些32位库(Mis)使用了高级指针位,因此历史上将32位程序限制为2GB是一种安全设置。

AnyCPU+Prefer 32位是一个较新的设置,默认情况下获取LARGEADDRESSAWARE设置,以便更好地访问64位平台上的资源。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54543938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档