当您运行VB或C#应用程序时,即使您的 计算机有很多 内存,也可能会出现OutOfMemoryException 。
每32位进程有一个2 ^ 32位(4 Gig)地址空间。这意味着每个指针的大小都是32位(4个字节),因此被限制为40亿个。
这相当于说车牌号由6位数组成,因此有100万个可能的号码。
4 Gigs分为一半:用户应用程序获取下半部分,操作系统获取上半部分。(这个界限可以改变:见下文)。
启动VS 2010. File-> New-> Project-> VB或C#Windows WPF应用程序。
粘贴下面的VB或C#代码。它创建一个堆,然后在循环中连续分配100Meg的内存,直到引发异常。
在我的具有8G内存的64位Windows 7机器上(你的数码相机或手机可能有 更多的内存!),我在分配之前分配了大约1.4Gig的内存。
#10 1,048,576,000
#11,153,433,600
#12 1,258,291,200
#13 1,363,148,800
类型'System.OutOfMemoryException'的异常异常被抛出。
现在选择Project-> Properties-> Compile-> Build Events-> PostBuildEvent Command,并 添加这两行
调用“$(DevEnvDir).. \ .. \ vc \ vcvarsall.bat”x86
“$(DevEnvDir).. \ .. \ vc \ bin \ EditBin.exe”“$(TargetPath)” / LARGEADDRESSAWARE
注意:报价的位置非常重要
第一行调用一个BAT文件,该文件可以在路径上提供各种工具。
第二个在目标二进制文件上运行EditBin,使用LARGEADDRESSAWARE 标志(这几乎是键盘上的所有左手键!)
同样取消选项:Project-> Properties-> Debug->启用Visual Studio宿主进程
这两行的唯一影响是调用EditBin在EXE中切换一点。当EXE启动一个进程时,整个进程被标记为能够使用2G以上的指针。
用这样的指针,高位是1,以2的补码表示,它是一个负数,有些应用程序可能没有被设计成与“负”指针一起工作。
现在,当我运行代码时,我获得了3.5 Gigs:超过两倍的内存!
#30 3,145,728,000
#31,350,585,600
#32 3,355,443,200
#33 3460,300,800
类型'System.OutOfMemoryException'的异常异常被抛出。
这个Editbin“技巧”在64位操作系统上运行良好。对于一个32位的操作系统来说,它也可以工作,但是你需要“bcdedit / set IncreaseUserVA 3072”(重新启动),你不会获得更多的额外内存。
想要更多的记忆?如果您使用的是64位操作系统,请尝试编译为64位:
VB:项目 - >属性 - >编译 - >高级 - >目标CPU - >任何CPU(或x64)
C#:Project-> Properies-> Build-> Platform Target->任何CPU(或x64)
#110 11,534,336,000
Iter#111 11,639,193,600
#112 11,744,051,200
#113 11,848,908,800
Iter#114 11,953,766,400
类型'System.OutOfMemoryException'的异常异常被抛出。
是的,这真的是我的8 gig机器上近12演出! 您也可以通过任务管理器进行验证。
一个64位进程有一个大小为64位(8字节)的指针。2 ^ 64 = 18,000,000,000,000,000,000。(1.8×10 ^ 19)
这大约有18艾字节,或90万年的DVD质量视频。
不过这是隔靴搔痒的数量可能棋牌类游戏,甚至是waaaay较小的电子数量,将适合在宇宙Ĵ(哈勃定律,宇宙大爆炸物理学)
当我第一次为微软工作时,我开发了一个thunking机制,允许32位应用程序调用16位DLL。(http://support.microsoft.com/kb/139070 )
我们认为任何人都无法用完32位地址空间!
如果车牌号码的长度从6位增加到12位,这将从100万人(中等城市人口)增加到1Trillion(1×10 ^ 12),是世界人口的200倍。
也可以看看
BCDEdit命令行选项
有效地使用多个堆
你的计算机用所有的内存来做什么?编写你自己的内存浏览器
LARGEADDRESSAWARE
使用XAML创建您自己的测试主机来运行您的单元测试
未记录的API和16位DLL
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Text;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用System.Runtime.InteropServices;
使用System.Diagnostics;
命名空间Heapcs
{
///
/// MainWindow.xaml的交互逻辑
///
公共 部分 类 MainWindow:Window
{
public MainWindow()
{
的InitializeComponent();
}
private void Window_Loaded(object sender,RoutedEventArgs e)
{
VAR hHeap = 堆 .HeapCreate(堆。HeapFlags .HEAP_GENERATE_EXCEPTIONS,0,0);
//如果FriendlyName是“heap.vshost.exe”,那么它使用VS托管进程而不是“Heap.Exe”
Trace .WriteLine(AppDomain .CurrentDomain.FriendlyName + “heap created”);
uint nSize = 100 * 1024 * 1024;
ulong nTot = 0;
尝试
{
for(int i = 0; i <1000; i ++)
{
var ptr = Heap .HeapAlloc(hHeap,0,nSize);
nTot + = nSize;
跟踪 .WriteLine(字符串 .Format(“Iter项目#{0} {1:N0}”,I,NTOT));
}
}
catch(Exception ex)
{
Trace .WriteLine(“Exception” + ex.Message);
}
堆 .HeapDestroy(hHeap);
Trace .WriteLine(“destroyed”);
Application .Current.Shutdown();
}
}
公共 类 堆
{
[ DllImport(“kernel32.dll”,SetLastError = true)]
public static extern IntPtr HeapCreate(HeapFlags flOptions,uint dwInitialsize,uint dwMaximumSize);
[ DllImport(“kernel32.dll”,SetLastError = true)]
public static extern IntPtr HeapAlloc(IntPtr hHeap,HeapFlags dwFlags,uint dwSize);
[ DllImport(“kernel32.dll”,SetLastError = true)]
public static extern bool HeapFree(IntPtr hHeap,HeapFlags dwFlags,IntPtr lpMem);
[ DllImport(“kernel32.dll”,SetLastError = true)]
public static extern bool HeapDestroy(IntPtr hHeap);
[ DllImport(“kernel32.dll”,SetLastError = true)]
public static extern IntPtr GetProcessHeap();
[ 标志()]
公共 枚举 HeapFlags
{
HEAP_NO_SERIALIZE = 0x1,
HEAP_GENERATE_EXCEPTIONS = 0x4,
HEAP_ZERO_MEMORY = 0x8
}
}
}
选项严格打开
导入System.Runtime.InteropServices
类MainWindow
私人 子 Window_Loaded(BYVAL发件人作为系统。对象,BYVAL Ë 作为 System.Windows。RoutedEventArgs)把手 MyBase .Loaded
暗淡 hHeap = 堆 .HeapCreate(堆。HeapFlags .HEAP_GENERATE_EXCEPTIONS,0,0)
'如果FriendlyName是“heap.vshost.exe”,那么它使用VS Hosting进程而不是“Heap.Exe”
Trace .WriteLine(AppDomain .CurrentDomain.FriendlyName + “创建的堆”)
Dim nSize As UInteger = 100 * 1024 * 1024
Dim nTot As ULong = 0
尝试
对于 i = 1 至 1000
Dim ptr = Heap .HeapAlloc(hHeap,0,nSize)
nTot + = nSize
跟踪 .WriteLine(字符串 .Format(“Iter项目#{0} {1:N0}”,I,NTOT))
下一个
抓住 EX 作为 例外
Trace .WriteLine(“Exception” + ex.Message)
结束 尝试
堆 .HeapDestroy(hHeap)
Trace .WriteLine(“已销毁”)
结束
结束 小组
末级
公共类堆
< DllImport(“kernel32.dll”,SetLastError:= True)> _
公共 共享 函数 HeapCreate(
BYVAL flOptions 作为 HeapFlags,
ByVal dwInitialSize 作为 UInteger,
ByVal dwMaximumSize 作为 UInteger
)作为 IntPtr
结束 功能
< DllImport(“kernel32.dll”,SetLastError:= True)>
公共 共享 函数 HeapAlloc(
ByVal hHeap 作为 IntPtr,
ByVal dwFlags As HeapFlags,
ByVal dwSize 作为 UInteger
)作为 IntPtr
结束 功能
< DllImport(“kernel32.dll”,SetLastError:= True)>
公共 共享 函数 HeapFree(
ByVal hHeap 作为 IntPtr,
ByVal dwFlags As HeapFlags,
ByVal lpMem As IntPtr
)作为 布尔值
结束 功能
< DllImport(“kernel32.dll”,SetLastError:= True)>
公共 共享 函数 HeapDestroy(
ByVal hHeap 作为 IntPtr
)作为 布尔值
结束 功能
< DllImport(“kernel32.dll”,SetLastError:= True)> _
公共 共享 函数 GetProcessHeap(
)作为 IntPtr
结束 功能
< 标志()>
公共 枚举 堆标志
HEAP_NO_SERIALIZE =&H1
HEAP_GENERATE_EXCEPTIONS =&H4
HEAP_ZERO_MEMORY =&H8
End Enum