【问题标题】:What is the max addressable memory space in a 32-bit C++ program?32 位 C++ 程序中的最大可寻址内存空间是多少?
【发布时间】:2014-08-06 16:00:02
【问题描述】:

在调试模式下,我看到指针的地址为 0x01210040, 但正如我意识到的那样,0x 表示十六进制对吗?并且有 8 个十六进制数字,即总共有 128 位被寻址?那么这是否意味着对于 32 位系统,前两位始终为 0,而对于 64 位系统,前两位始终为 0?

另外,我可以问一下,对于一个 32 位程序,只要我留在堆中并且只使用 malloc(),我是否能够分配多达 3GB 的内存?还是 Windows 系统在单个线程上存在一些限制? (我使用的IDE是VS2012)

因为实际上我是在 64 位系统中运行一个 32 位程序,但是当它只分配大约 1.5GB 内存时,该程序因内存泄漏而崩溃……我似乎无法弄清楚为什么.

(哎呀……对不起,伙计们,我想我在第一个问题上犯了一个简单的错误……确实,一个十六进制数字是 4 位,而 8 是 32 位。但是这是另一个问题……地址是如何表示的64位程序?)

【问题讨论】:

  • 2^32 字节 = 4294967296B = 4GB
  • 每个十六进制数字是 4 位,所以 8 个十六进制数字 == 32 位...
  • arrrgh!! 没错...为什么我只是有一个疯狂的想法,每个十六进制数字都是两个字节...
  • 你到底在问什么?在 32 位程序中,地址是 32 位值。在 64 位程序中,地址是 64 位值(尽管only the low 48 bits are used)。十六进制表示仅用于向人类显示地址,就像它们以二进制表示的所有数字一样(这就是 bit 的含义)
  • 在线性地址空间中,可能的地址空间为4GB。需要注意的是,许多硬件项目都是内存映射到地址的。所以你的程序可能无法处理整个范围。

标签: c++ memory memory-leaks


【解决方案1】:

对于 32 位 Windows,该限制实际上是每个进程可用 2GB,虚拟地址从 0x00000000(或简称为 0x0)到 0x7FFFFFFF。其余 4GB 地址空间(0x800000000xFFFFFFFF)供 Windows 本身使用。请注意,这些与实际的物理内存地址无关。

如果您的程序支持大地址空间,则此限制在 32 位系统上增加到 3GB,在 64 位 Windows 上运行的 32 位程序则增加到 4GB。

对于大地址空间感知程序 (IMAGE_FILE_LARGE_ADDRESS_AWARE) 的更高限制,请参见此处:

您可能还想查看Virtual Memory article on Wikipedia 以更好地了解虚拟地址和物理地址之间的映射是如何工作的。上面第一个 MSDN 链接也有一个简短的解释:

进程的虚拟地址空间是虚拟内存的集合 它可以使用的地址。每个进程的地址空间是 私有的,除非它是共享的,否则不能被其他进程访问。 虚拟地址并不代表实际的物理位置 内存中的一个对象;相反,系统维护一个页表 每个进程,这是一个用于翻译的内部数据结构 虚拟地址转换成对应的物理地址。每个 当一个线程引用一个地址时,系统翻译虚拟地址 地址到物理地址。 32位的虚拟地址空间 Windows 大小为 4 GB,分为两个分区: 一个供进程使用,另一个保留供进程使用 系统。有关 64 位虚拟地址空间的更多信息 窗户,见Virtual Address Space in 64-bit Windows.


编辑:作为user3344003 points out,这些值不是您可以使用 malloc 分配或以其他方式用于存储值的内存量,它们仅表示虚拟地址空间。

【讨论】:

  • 谢谢!但实际上我的系统是 64 位的,并且我没有声明 MSDN 中描述的 2GB 限制......但是程序本身本质上是 32 位的,所以我想我最多可以使用 4GB(或者它是 32 位??检查程序是否为 64 位?)
  • 检查您在 Visual Studio 中的设置,在那里您可以将构建体系结构更改为 32 位或 64 位。如果您仍然不确定,请使用dumpbin 工具,如here 所述
【解决方案2】:

有许多限制会限制您的 malloc 分配的大小。

1) 位数,限制地址空间的大小。对于 32 位,即 4B。 2)系统细分为各种处理器模式。现在,通常 2GB 给用户,2GB 给内核。 3) 地址空间可能会受到页表大小的限制。 4) 总虚拟内存可能受页面文件大小的限制。 5) 在你开始 malloc'ing 之前,虚拟地址空间中已经有一些东西(例如,代码堆栈、保留区域、数据)。您的 malloc 需要返回一个连续的内存块。它可以返回的最大理论块必须适合虚拟内存的未分配区域。 6) 您的内存管理堆可能会限制可分配的大小。

我可能省略了其他限制。

-=-=-=-=-

如果你的程序在通过 malloc 分配 1.5GB 后崩溃了,你有没有检查 malloc 的返回值是否不为空?

-=-=-=-=-=

分配大块内存的最佳方法是通过操作系统服务将页面映射到虚拟地址空间。---不使用 malloc。

【讨论】:

    【解决方案3】:

    参考以下article

    对于在 32 位 Windows 中启动的 32 位应用程序,所有提及的数据类型的总大小不得超过 2 GB。 同样的32位程序在64位系统中启动,大约可以分配4Gbytes(实际约3.5Gbytes)

    由于 windows 占用的空间,您正在查看的实际数据约为 1.7 GB。

    你是怎么知道它崩溃时分配的内存的?

    【讨论】:

    • yes...32bit 程序在 64 位窗口中,我正在检查任务管理器,看到线程占用越来越多的内存,直到它在 1.5 崩溃
    猜你喜欢
    • 2011-11-24
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2012-09-25
    • 2012-01-23
    • 2021-04-08
    • 2012-01-07
    相关资源
    最近更新 更多