关于32位程序申请大内存问题(1.6G). 我在win7 64系统上面测试
Visual studio 10- int* Test=new int[1024*1024*200];
- int* Test2=new int[1024*1024*200];
申请1.6G内存.抛出:cpptest2.exe 中的 0x770e15ee 处有未经处理的异常:
Microsoft C++ 异常: 内存位置 0x0044f660 处的 std::bad_alloc。
这只是一个简单的测试 . 我做三维仿真.. 内存要用到2G-4G左右.. 如何在64位系统 32位程序申请到大内存啊..------解决方案--------------------------------------------------------32位程序不可能申请大于4G的内存,linux在X86系统下,理论上用户态可以申请3G内存(有1G的地址空间留给内核),内核态可以申请4G内存,windows你需要查一查其系统规范。------解决方案--------------------------------------------------------用文件读写模拟内存读写是在32位操作系统下使用超过4G内存的不二法门。
参考_lseeki64
在windows 32位操作系统中,每一个进程能使用到的最大空间(包含操作系统使用的内核模式地址空间)为4GB , 在通常情况下操作系统会分配2GB内存给进程使用,另外2GB内存为操作系统保留, 例如安装了64GB内存,在服务器上安装了SQL / Exchange / ISA / IIS ..... ,那么每个进程(SQL /Exchange / ISA /III ) 能用到的最大空间通常为2GB ,但是微软允许通过在boot.ini 中加入/3GB参数,将操作系统保留的2GB内存减少到1GB,从而将分配给进程的内存提高到3GB 。
如果希望应用程序能使用更大的内存,他就需要将他的操作系统和应用程序迁移到64 位平台上。具体说明可以看下面的文章进程地址空间 所有 32 位应用程序都有 4 GB 的进程地址空间(32 位地址最多可以映射 4 GB 的内存)。对于 Microsoft Windows 操作系统,应用程序可以访问 2 GB 的进程地址空间,称为用户模式虚拟地址空间。应用程序拥有的所有线程都共享同一个用户模式虚拟地址空间。其余 2 GB 为操作系统保留(也称为内核模式地址空间)。所有操作系统版本(从 Windows 2000 Server 开始,包括 Windows Server 2003)都有一个 boot.ini 开关,可以为应用程序提供访问 3 GB 的进程地址空间的权限,从而将内核模式地址空间限定为 1 GB。
地址窗口化扩展插件 (AWE) 通过允许访问尽可能多的操作系统支持物理内存来扩展 32 位应用程序的功能。AWE 可以将最大内存容量 64 GB 的一部分映射到用户地址空间来实现此功能。应用程序缓冲池和 AWE 映射内存之间的映射通过操作 Windows 虚拟内存表来完成。
为了支持 3 GB 的用户模式进程空间,必须将 /3gb 参数添加到 boot.ini 文件中并重新启动计算机,从而使 /3gb 参数生效。设置此参数后,用户应用程序线程可以寻址 3 GB 的进程地址空间,而为操作系统保留 1 GB 的进程地址空间。注意: 如果计算机上有 16 GB 以上的可用物理内存,操作系统需要 2 GB 的进程地址空间供系统使用,因此只能支持 2 GB 的用户模式地址空间。为了让 AWE 能够使用 16 GB 以上的内存,应确保 boot.ini 文件中没有 /3gb 参数。否则,操作系统就不能寻址 16 GB 以上的内存。
AWE方式虽然可以访问超过2G的内存,但其本身也有一些问题,首先必须要锁定内存,其次需要自己写内存管理程序来管理这些内存,.net framework 无法在AWE 扩展的内存中创建托管堆。其实很多应用只是想申请比2G稍多一些的内存,最简单的方法还是采用/3GB开关来实现。本文将讲述如何利用 /3GB开关来让32位操作系统下.net 应用程序申请超过2GB的内存。
首先简单说一下这个 /3GB 开关 (知道的可以不看)
默认情况下,Windows 可以对总计 4 千兆字节 (GB) 的虚拟地址空间进行寻址。默认情况下,此地址空间中的 2 GB 为内核(操作系统)保留,另外 2 GB 是为用户模式程序保留的。当你将 /3GB 开关放入操作系统的 Boot.ini 文件中时,你就重新分配了虚拟地址空间,给用户模式程序提供 3 GB 的空间,同时将内核限制为 1 GB。
设置办法:C:\boot.ini 文件做如下修改:
[boot loader]timeout=30default=multi(0)disk(0)rdisk(0)partition(2)\WINNT[operating systems]multi(0)disk(0)rdisk(0)partition(2)\WINNT="????" /3GB
如下操作系统可以支持 /3GB 开关
Windows XP Professional
Windows Server 2003Windows Server 2003, Enterprise EditionWindows Server 2003, Datacenter EditionWindows 2000 Advanced ServerWindows 2000 Datacenter ServerWindows NT Server 4.0, Enterprise EditionWindows VISTA , Windows 7 和 Windows server 2008 也支持这个开关
详见
设置完后重新启动系统,这时应用程序就可以申请超过3G的内存了。一切好像到这里就该结束了,然而并非如此。
当我运行我在.net framework 下做的测试程序时,我发现3GB开关打开后,这个测试程序依然无法申请超过2G的内存,内存申请到1.5G以上时就无法再分配内存了。
查找资料后我发现,操作系统在支持/3GB参数后应用程序也要做相应的修改,告诉操作系统可以按照/3GB方式运行才行,我想这很可能是出于对应用程序兼容性方面的考虑。
为了告知操作系统这个应用程序可以支持/3GB方式,我们需要往exe 文件头中添加一个 IMAGE_FILE_LARGE_ADDRESS_AWARE
标志。添加的方式很简单:
在你的系统的 Program Files\Microsoft Visual Studio 8\VC\bin 目录下找到 editbin
这个可执行文件,在命令行下执行:
editbin
/LARGEADDRESSAWARE yourapplication.exe 这里的yourapplication.exe 需要输入的是你的.net 应用程序的路径名加文件名。
执行了这条语句后,我再次运行测试程序,内存可以申请到 2.5G了,比2GB模式下多了1G内存可以使用。
最后多罗嗦一句,为什么.net 应用程序在 2GB 情况下只能申请最多 1.4-1.6 GB 的内存?
这是因为.net 的垃圾回收器在工作时需要拷贝 live objects,.net framework 需要为它保留一定空间的内存来完成这些拷贝工作。这也是为什么Microsoft 建议asp.net 应用程序内存分配的上限最好设置为800M的原因.
.net 应用程序如何优化性能,参见下面链接,大家有兴趣可以去看看,这里不再多说了,离主题有点远了。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4G内存的**——如何使用4GB(开启3GB和PAE)
Windows Vista是一款相当耗费资源的操作系统,特别是内存。要提升系统性能,最简单也最有效的方式是为系统扩充尽可能多的内存,windows 7当然也不例外,虽然不像vista那么耗资源。现如今内存已是大白菜,4G及以上内存必定是趋势。windows 7最高能支持多少物理内存呢? 我们先来看看vista: 根据微软给出的规格,除Starter版仅支持1GB内存外,其他版本的Windows Vista(32位)均能够支持4GB的“内存”——当然,指32位x86系统。需要注意的是,这里所谓的“4GB”并非等同于真正的物理内存,而是指可用的内存寻址空间。 对32位系统而言,4GB是其能够寻址空间的极限,除非通过PAE(Physical Address Extension 物理地址扩展)将4GB之上的内存通过映射的方式作为4GB空间中的页面来扩展。而在这4GB的地址空间中,必须为计算机的系统资源如BIOS、显卡、PCI-Express等PCI接口留出位置。 系统所支持的4GB寻址空间都包括哪些:首先,BIOS至少要占去512KB或者1MB,显卡要占去略大于其视频RAM的空间,比如说,对于在高分辩率下使用Aero Glass的情况而言,256MB显存是必需的,这就必须在4GB的寻址空间中为显卡的256MB视频RAM留出位置;第三,对基于x86的计算机系统而言,其还必须为其他的PCI设备保留相当部分的寻址空间,比如各种IO设备等。这样,系统在寻址真正的物理内存之前,系统中已经被各种资源占用512MB到1GB的寻址空间,也即是说,系统真正能够使用的物理内存大致在3 GB到3.4 GB之间。 这对于象Win7这样一款以1GB RAM越跳的系统而言,系统内存的可扩充空间实在太小,尤其与当年Windows XP 128MB-4GB的内存范围相比。而且,虽然Win7 X86从内核上来说应该是能够支持PAE的。当然,也需要硬件厂商特别是CPU、芯片组与主板厂商的配合。 另一方面,在32位的Windows系统——不仅仅Windows Vista / Win7中,所支持的4GB寻址空间被分成两部分:其中2GB可被应用程序使用,而另外的2GB则被系统内核占用。因此,即使对于系统中安装了4GB内存的Win7而言,应用程序所能够使用的内存也被限制在2GB之内,从而在某些情况下仍难免会出现“内存不足”的情况。对此,server用户虽然可以通过微软的4GT RAM Tuning来将内核的内存起始位置移至3GB处——以在Boot.ini中添加“/3GB”开关实现,即将为内核分配的虚拟地址空间缩小到1GB,而将应用程序可使用的地址空间扩展到3GB——但距理想程度仍有距离。 当然,如果64位,问题就好办多了,Windows Vista x64可支持的内存从8GB(Windows Vista Home Basic)到128GB(Windows Vista Ultimate),Win7也一样,类似的寻址限制不复存在。但在软件和游戏上,64位的用户要期望更多的软件和游戏厂家的支持。
附:Vista / windows 7如何开启PAE
1进入cmd:点击开始菜单,在搜索框中输入”cmd“,按下 Ctrl + Shift + Enter (进入cmd的管理员模式)2输入如下命令BCDEdit /set PAE forceenable Windows 这里的BCDEdit是关于命令行的启动配置编辑器。使用上面的命令,你能启用物理地址扩展(PAE),让支持的内存大于4GB Vista / windows 7开启3GB因为32位windows默认应用程序只能使用2G内存,剩下的都保留给系统内核了,所以还要开启3GB1进入cmd:点击开始菜单,在搜索框中输入”cmd“,按下 Ctrl + Shift + Enter (进入cmd的管理员模式)2,输入如下命令bcdedit /set increaseuserva 3072 来使得windows把2G以上的内存也分配给应用程序! 补充XP和 2003 的开启方法:1.打开 Windows 资源管理器。 2.在“工具”菜单上,单击“文件夹选项”。 3.在“查看”选项卡上,单击“显示所有文件和文件夹”,清除“隐藏受保护的操作系统文件”复选框,然后单击“确定”。如果显示警告对话框,单击“是”以继续。 4.在根文件夹(如 C:)下查找 Boot.ini 文件并删除它的只读属性。 5.打开 Boot.ini 文件,然后将 /PAE 参数添加到 ARC 路径中,如以下 Windows Server 2003 Datacenter Edition 示例所示: multi(0)disk(0)rdisk(0)partition(2)\%systemroot%="Windows Server 2003, Datacenter Edition" /PAE 以xp为例,修改页面Boot.ini文件如下: timeout=30 default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /PAE 6.在“文件”菜单上,单击“保存”。 7.还原 Boot.ini 文件的只读属性。 8.为使更改生效,请重新启动计算机。
由于在32位处理器架构下,对内存的访问限制在4GB以下的空间。为了突破 4GB的限制,现在的32位至强处理器采用一种叫PAE(物理地址扩展)的技术,来实现对超出4GB空间的物理地址的访问。PAE实际上采用了36位的地址总线,这样理论上可以支持64GB内存空间的寻址。
PAE使得处理器可以支持访问更多的内存空间,但是这还需要操作系统的支持。由于操作系统本身也是32位的,所以需要在操作系统上做相应的处理来支持处理器。Windows系统采用AWE(Address Windowing Extension)来进行处理。具体结构如图2所示。此外,Linux系统在2.4内核以后也支持PAE和超过4GB的内存空间处理。32位系统,地址空间是4G。这个没错。用户空间指的是应用程序可以直接访问的地址,系统空间指的是应用程序不能直接访问,必须转到内核模式,由操作系统访问。任何操作系统都分用户空间和系统空间,Unix, Linux都是。
Windows95, Windows 98, WindowsME系列2G用户空间 + 2G系统空间, 2G的系统空间中含有多个进程共享内存的空间和Win16的程序的代码,这就是Win9x系列容易死机的原因之一。WinNT, Win2000, WinXP系列2G用户空间 + 2G系统空间.(没有Win9x系列的进程共享内存等等)那么是不是我启动10个应用,那操作系统占有了10*2G这么多空间? 首先,要搞清楚内存和地址空间的区别。内存是内存,地址空间是地址空间(太累了,我用memory代替内存,address space代替地址空间吧). 不管你有多少memory,256,还是512M,32位系统的每个应用都有4G的地址空间(只不过它不能访问上2G罢了).win2000下,你的程序最多可以使用2G空间,并不是说你还就可以分配2G的内存了,一般情况下,内存分配到一个值是会失败的。比如,你的物理memory = 256M,你的页交换文件大小=256M,那么你分配个516M内存看看,失败!物理内存和页交换文件加起来才512M呢. 其次,操作系统真的占有了2G的内存吗?也不是。你的程序启动后,操作系统的代码和数据映射到程序的上面2G的空间,只是映射,不是说再启动一个实例放那儿。操作系统要映射一片内存的内容到一个区域是多简单的事情。操作系统一般把系统代码和数据映射到应用程序的上面2G的同一个地方。2个应用程序,它的上面2G空间的代码数据大致上一样(不完全一样,因为还是有些和应用程序相关信息,不过应用程序访问不到,得由系统通过内核态访问).严格说来,下面2G也不是应用程序都能用,0到64K这个空间就不能用,至于为什么,回到DOS时代吧!如果没搞多DOS那就不必要深究了。总之这是故意的。你的指针指到这儿肯定会出错,读都不能读。故意不让你读!哈哈。 其实大多数应用程序比如你用VC写个程序,它的入口地址是从4M开始,也就是0x00400000,你看看 yourApp.hInstance的值吧!它就等于0x00400000.越讲越远了,为什么hInstance是程序的入口地址,跑题了!别扔砖头啊!那么应用程序怎么申请大于2GB的空间呢?办法1:就是上面的朋友提过的 通过 /3GB或者/USERVA开关。boot.ini 里头加上这个开关,系统会让出1G给应用程序访问。系统自己只用1G。这样子不是什么好办法。微软临时的方案而已。应用程序link时加上 LARGEADDRESSAWARE,在生成EXE的时候设置一个标志位,这个位系统看到了就让你访问 3G的空间(但是内存+页交换太小,你分配一样会失败)./3GB指定3G,/USERVA指定一个值,不是死的3G.办法2:通过AWE (Address Window Extension),地址窗扩展窗?是的,窗。你可以人认为是一个buffer,用来作为中间物,给2边的东西倒腾。socket接受发送数据也有窗的概念,一样的。 要细看AWE,你到MSDN上查关键是AWE或者Address Window Extension。Google上Goole一把。你有了2G甚至更多的内存(啥机器都有,你不能怀疑一个32位系统装个20G内存会有问题吧?硬件可以做的)可以这么干。没有的话就别这么做了,没什么用.AWE的原理很简单,你在比如4G的物理内存上,分配的一片物理内存X, 你再分配的一片虚拟内存(地址空间)Y,把 X 和 Y 通过address window映射。你可以在这片虚拟内存里头访问4G的物理内存。最多访问多少要看你的参数设置了。 AllocateUserPhysicalPages分配物理内存, VirtualAlloc申请虚拟内存,MapUserPhysicalPages进行映射。没什么难的.MSDN有个sample做这个事情,看看吧! 这么多关键字了应该好查到了。代码我不贴了 ,占篇幅。 顺便说一下,内存文件映射并不把什么映射到(2~4G)这范围。它是进程共享数据的方式,并不是扩大内存的方式。不过如果你有个大硬盘,创建这么个映射来保存/修改数据也是可以的,这不要求大的内存。和内存没关系。