0

我有一个关于内存分配的问题,尤其是在使用 MSVC2019 时。

我有一个编译为 x64 的 C++ 程序。通过调试我看到,分配变量会产生非常高的指针地址,指向前 4GB 地址空间(32 位)上的位置。如果我在任务管理器中检查程序,我发现它只使用了大约 30-50MB 的内存。

当实际上4GB以下的整个地址空间未被使用时,变量没有分配到虚拟内存空间的下部是什么原因?

我希望分配从低地址开始,直到使用的第一个 4GB 空间,不需要为此分配空间。

为什么这对我来说很有趣:我有一个包含超过 15 年历史的 C++ 代码的大型软件,它并非到处都准备好成为 64 位,在许多地方它将指针转换为 32 位类型,因此指针被损坏。最初的作者很可能假设指针是 32 位的。当编译为 64 位时,实际上应该也是如此,因此程序没有使用太多内存,内存使用量不会增长超过 4GB。并且似乎在使用 2010 年的编译器进行编译时,并没有出现这个问题,可能是那个时候内存分配导致了第一个 4GB 块中的地址,即使是为 x64 编译的也是如此。

我的问题是:这种分配策略会以某种方式影响 MSVC++ 2019 吗?例如。指示他的编译器/链接器/内存管理器优先分配前 32 位空间,直到不再需要?或者,为内存管理器提供的虚拟地址空间设置大小限制,例如。通过设置为 2GB,我可以实现永远不会有任何指针指向超过 4GB 的已分配块。这样,假设指针为 32 位,旧代码将在强制转换操作中存活下来。

我已经尝试在链接器选项中设置 NO 以获得高内存感知,并检查了堆参数,但它们都没有帮助。

谢谢!

4

2 回答 2

0

如果您的程序假定指针是 32 位的,那么您只需要针对 32 位进行编译,直到您使用 ifdef 来检查您正在编译的内容的正确声明。

只需从下拉列表中选择 x86 而不是 x64 作为解决方法,直到您对旧代码进行现代化改造。

使用大地址空间可以做更多事情,并且由于操作系统无论如何都将这些映射到物理内存的部分,编译器只是选择了将地址空间的不同部分分开以用于不同目的的好处。

有一些方法可以创建自定义堆并在特定地址空间可用时分配东西,但是与正确分配正确大小相比,将这些处理到代码中可能需要同样长的时间并且会倒退。

于 2021-05-21T12:18:07.867 回答
0

欢迎来到虚拟内存的世界!事实上,为了动态分配内存,标准库请内核提供它。并且只有内核负责分配给程序的虚拟地址。由于每个进程都有自己的虚拟地址转换器,因此可以为多个进程分配相同的虚拟地址。作为程序员,您永远不应该担心这一点。使用内核给你的内存地址并继续。如果假设指针不能超过 32 位,则必须使用遗留代码,则不应该在 64 位模式下编译它,而只能在 32 位模式下编译。

于 2021-05-21T12:38:45.897 回答