我有一个 x32 的混合模式应用程序。所以只有2G内存可用。应用程序处理一些大数据并在非托管堆中分配大约 1.5G。然后它释放分配的非托管内存而不会泄漏。但下一步是在托管模式下处理大约 1.5G。当分配了大约 200M 的托管内存时,尝试在 List 中添加元素时应用程序崩溃了。正如我所想,非托管堆管理器获取 1.5G 的内存,在其中分配对象,然后释放对象但不释放堆内存以供托管堆管理器访问。托管和非托管内存管理器如何共享进程的内存?我该如何解决这样的问题?
这是一个示例代码,在分配和释放非托管代码后尝试分配托管内存时抛出异常。它必须在 x32 中编译。为什么会这样?
int size = 1024 * 1024 * 1024 / 2 / 10;
char* * cppArray = new char*[size];
for(int i = 0; i < size - 1; i++)
{
char *str = (char*)malloc(10 * sizeof(char));
strcpy(str, "AAAAAAAAAA");
cppArray[i] = str;
}
for(int i = 0; i < size - 1; i++)
{
char* str = cppArray[i];
free(str);
}
delete[] cppArray;
List<String^>^ pArray = gcnew List<String^>();
size = 1024 * 1024 * 1024 / 2 / 7 / 2 / 2;
for(int i = 0; i < size - 1; i++)
{
pArray->Add(gcnew String("AAAAAAAAAA" + i.ToString()));
}
谢谢。
最佳答案
对于第一部分,任何曾经被 malloc'ed 的东西都会被 malloc'ed。原因是 malloc()
从操作系统获取内存的方式,即增加堆最大地址。因此,要再次释放它,您必须确保不再有对任何地址的引用,否则会出现段错误。
现在有一种可能可以解决这个问题的方法,即mmap()
找到一个使用 mmap()
的分配器,或者它在 MS 语言中的任何名称。确保它可以使用 munmap()
之类的东西再次释放它。
在内存映射地址中分配您的数据,并确保在取消映射之前没有留下对它的引用。
附言。 也像@JSF 所说的那样,使用 LargeAddressAware 编译并在您的操作系统上启用 3GB。 并且即使在 32 位系统上也要确保你至少有 4GB 内存,操作系统使用了其中一些用户无法访问的内存。即使每个程序只能访问 3GB,加起来仍然非常快超过 3GB。
关于c# - C++ 混合模式应用程序中的内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33098016/