.Net处理非托管内存的方式与C++运行时/二进制可执行文件不同
本文关键字:运行时 C++ 二进制 可执行文件 方式 处理 内存 Net | 更新日期: 2023-09-27 18:25:03
使用p/invoke与具有大量静态数据分配的Fortran库进行交互的.Net应用程序在Windows上远远低于2 GB静态数据限制时无法加载该库。我通过p/invoke成功加载的最大静态代码大小约为1GB。如果我写一个简单的C程序来加载库,我可以加载最大1.9 GB的静态数据。两个测试应用程序都是32位的。
托管应用程序试图通过LoadLibrary加载库,但失败了,Marshal.GetLastWin32Error返回的错误消息是"没有足够的存储空间可用于处理此命令"。CLR处理非托管库的静态内存分配的方式与C++运行时为二进制可执行文件提供的方式有区别吗?
在C程序中也没有太多的保证,它只需要在一个基址加载一个糟糕的注入DLL,就可以将可用地址空间一分为二,操作系统再也找不到足够大的洞来容纳这个巨大的部分。
更糟糕的是,在.NET程序中,当你的pinvoke调用开始运行时,它已经加载了很多代码和数据。例如,至少有10堆。最大的漏洞通常约为650-750兆字节,但仅在启动后立即出现。SysInternals的VMMap实用程序可以向您显示土地的布局。
要想把洞弄大,你几乎无能为力。请确保您的.NET版本足够新,以便在64位版本的Windows上获得4GB的地址空间。您的Fortran DLL需要/LARGEADDRESSAWARE才能正常工作。重构Fortran代码,使其从堆中进行分配,这肯定是你不想做的事情。现在是时候开始构建它的64位版本了,这很简单。