【问题标题】:Win32 compiler option and memory allocationWin32 编译器选项和内存分配
【发布时间】:2020-07-14 15:13:20
【问题描述】:

我尝试编译以下代码:

extern "C" {
    #include "netcdf.h"
}

int main() {
    const int Ntime = 336;
    const int Nlon = 1442;
    const int Nlat = 1021;
    double* dhsum_vals = new double[Ntime * Nlat * Nlon];
}

使用 32 位版本编译时,我收到错误 C2148“数组总大小不得超过 0x7fffffff 字节”。我认为,这里的问题是 32 程序不允许在这里使用我想要的尽可能多的内存。如果我使用 64 位版本进行编译,则会收到错误消息,即下载 32 位版本时找不到 netcdf。所以,我的解决方案是下载 64 位版本的 netcdf 库。但是,我在采用 32 位版本时的意图是它应该更兼容。除了使用 64 位版本的 netcdf 之外,我的问题还有其他解决方案吗?

【问题讨论】:

  • double* dhsum_vals = new double[Ntime * Nlat * Nlon]; 那不在堆栈上。但是,如果这是一个 32 位程序,由于 2GB 用户空间/内核拆分和内存碎片,默认情况下,Windows 上的最大分配可能会被限制在 1.2GB 左右。
  • @drescherjm,您是对的,误读并假定堆栈。我的错。
  • /LARGEADDRESSAWARE 链接器标志可以帮助解决这个问题以及 dll 变基,但是切换到 64 位会简单得多。我记得在 2000 年代初玩过这个游戏,但我很高兴我们将所有机器都切换到 x64,所以我不再需要处理这个问题。我在这个答案中提到过:https://stackoverflow.com/a/19911739/487892
  • 使用动态内存(malloc()new)会产生一些开销(“簿记”)。对于一个巨大的数组,浪费的开销百分比很小,但是由于您不需要它是动态的(是吗?),您不妨将其静态分配,假设您不需要多个副本它(例如,如果您使用 C++ 类进行编程,则每个类实例一个)。假设你的整个程序中只有一个这样的数组,你可以在任何函数之外声明它,它就变成了“全局的”。
  • 如果您希望它成为 C++ 类的成员,并且如果您只需要一个这样的数组而不管您将创建的类实例的数量,那么您可以声明它@987654326 @ 然后整个程序中只有一个这样的数组,由该类的所有实例使用。如果(回到之前的“全局数组”)您在定义前面添加了static 关键字,那么该数组仍将是静态分配的(“全局”),但它只会在该翻译单元内被知道( C++ 文件)。请注意,术语“静态”和“静态分配”只是松散相关。

标签: c++ compatibility


【解决方案1】:

在 Microsoft Windows 上,32 位进程的virtual address space 被限制为 2^32 字节,大约为 4 GB。但是,较高的 2 GB 由系统保留,因此您实际上只有大约 2 GB 的地址空间。

此外,此地址空间是碎片化的,因此您将无法在一个连续的块中分配 2 GB。如果您尝试几个较小的内存分配,您最多可以获得 2 GB。

虽然 32 位进程可以使用 Address Windowing Extensions API 使用超过 4 GB 的内存,但这需要特殊的安全权限并使您的代码变得不必要地复杂,因为您无法将正在使用的所有内存都映射立即进入您的虚拟地址空间。因此,我强烈建议您在处理大量内存时编译 64 位版本的应用程序。

我认为使用 64 位不会降低程序的兼容性,因为几乎所有现代硬件和操作系统都支持它。

【讨论】:

  • 我记得大约 15 年前调查过 AWE。为我需要的东西增加了太多的努力和复杂性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-27
  • 2013-04-11
  • 1970-01-01
相关资源
最近更新 更多