我只是在我的Windows应用程序项目中写了两行
double[] results = new double[100000000];
double[] results1 = new double[100000000];
在第二行(results1)我得到了异常'System.OutOfMemoryException'被抛出。
我的系统配置是
RAM- 4 gb
操作系统 - Windows 7
处理器 - 两核2.93 Ghz的英特尔核心
如何解决此错误以及发生此错误的原因
好的,因为大部分答案都适用于通用列表
List<int> results1 = new List<int>();
List<int> results2 = new List<int>();
for (int i = 0; i <= 100000000; i++)
{
results1.Add(i);
results2.Add(i);
}
我在这里也得到了同样的错误
答案 0 :(得分:8)
创建数组时,内存分配器将尝试保留分配点所需的总内存量。在这种情况下,每个元素将为8个字节。在这种情况下,OOM非常简单,没有足够的内存来分配这样的大型数组。在标准的32位Windows配置中,对于用户代码和数据,每个进程最多只能有2GB的内存地址空间,但实际上由于内存碎片,它通常比这少得多。在碎片化的情况下,在处理大型数组时,OOM被更好地解释为“找不到足够大的连续内存部分”。
答案 1 :(得分:5)
你不应该分配那些不适合内存的大型数组。只需使用列表并根据需要添加元素:
var results = new List<double>();
的引用
int[] array = new int[5];
此数组包含来自的元素 array [0]到array [4]。新的运营商 用于创建数组和 将数组元素初始化为它们的 默认值。在这个例子中,所有 数组元素初始化为 零
所以你需要有足够的内存来保存这些默认值。
答案 2 :(得分:5)
这是一个800MB阵列,您尝试加载到win32进程空间(2GB)。它也需要连续,这使得它更难。简单 - 在LOH中找不到一个足够大的连续区块,以便将所有这些整合在一起。
三个选项:
double[][]
有10000个内部数组,每个数组长度为10000 - 只需执行一些/
和%
代码即可进入正确的块答案 3 :(得分:2)
我可能错了,但通常(意思是,至少在大多数语言中)分配数组时,这意味着您要求连续内存块。具有100,000,000个元素的单个双精度数组将需要100000000 * 8字节的内存(+可能的开销),大约800兆字节。即使你说的内存量(总计),也不一定意味着空闲内存是连续的,它可能被分割成不同大小的多个空闲区域,并且分配将失败。
答案 4 :(得分:2)
一个可能的原因是虚拟地址空间碎片:内存管理器可以找到第一个800MB连续的地址空间块。但它找不到第二个。
答案 5 :(得分:1)
据我所知,列表的工作原理如下:如果列表的长度超过2 ^ n,则分配另外2 ^ n个元素。因此,在列表的长度为67108864(= 2 ^ 26)时,它将分配另外2 ^ 26个元素。如果我正在运行您的代码,那也正是错误发生的地方。如果你使用长变量而不是int,你将得到长度为33554432的错误,正好是2 ^ 25。这也是有道理的。
所以你的第一个列表 - 在它变得超过2 ^ 26的那一刻 - 已经分配了一个2 ^ 27 * 4字节的内存空间,因为一个int需要4个字节,所以这是2 ^ 29个字节。在您尝试为第二个列表分配更多空间的那一刻,您的内存超过2 ^ 30字节,即1GB。
这就是为什么我认为存在一个基本内存RAM限制,它不仅仅是关于自由连续的地址空间,而且还有大约1 GB的RAM限制。我不确定这个限制到底在哪里。
在32位机器上有一些关于类似问题的帖子here - 我不知道你的win 7是32还是64位。 编辑:我现在以64位模式运行您的应用程序,问题就消失了。所以我可以再次参考上面的帖子。您应该将项目属性中的平台更改为64位。
只留下一个问题:为什么你想要这么大的名单?这实际上是内存消耗,有很多方法可以避免这样的分配。
希望有所帮助。
答案 6 :(得分:0)
错误的原因是数组太大,以至于在运行代码时会占用系统上的所有免费ram。达林所说的是对的。制作一个大的数组是没有意义的。迭代将需要永远,并且在大多数系统上都会占用太多内存。