【问题标题】:Allocating an Array greater than 2GB in C (or C++)在 C(或 C++)中分配大于 2GB 的数组
【发布时间】:2019-02-24 22:08:47
【问题描述】:

我正在运行 Windows 10 64 位。我的编译器是 Visual Studio 2015。

我想要的是:

unsigned char prime[UINT_MAX];

(和更大的数组)。 该示例给出编译器错误 C2148,因为该应用程序是“Win32 控制台应用程序”。同样,我不能使用 new 创建数组;同样的问题。我将它构建为“x64 版本”,但我猜 WIN32 控制台部分正在获胜!

我想释放我的 64 位操作系统的力量,摆脱对数组索引的烦人 INT_MAX 限制,即正确的 64 位操作。我的应用程序是一个简单的 C/C++ 东西,除了命令行界面之外,它既不需要也不想要任何东西。

我确实安装了(免费)Visual Studio 2017 应用程序,但它没有提供我喜欢的简单控制台应用程序(所以我卸载了它)。

我是否可以在 Visual Studio 中构建其他一些应用程序类型来访问超过 4GB 的内存?是否有其他(免费)编译器可以用来在 Windows 下获得完整的 64 位访问权限?

【问题讨论】:

  • 为 x64 架构而不是 x32 编译您的程序。
  • 如果你没有足够的连续可用内存,那么分配也会失败
  • "我确实安装了(免费的)Visual Studio 2017 应用程序,但它没有提供我喜欢的简单控制台应用程序”但是.. Visual Studio 2017 有控制台应用程序的模板..
  • 如果你试图在堆栈上声明该数组,它会因为内存不足以外的原因而失败。
  • 过滤掉推测性噪音,即使在 x64 中,VC++ 允许的总连续原生数组大小(以字节为单位)为 2147483647 字节 (0x7ffffffff)。您引用了错误代码,但没有引用错误消息,这似乎与您的困惑有关。如果您需要更多,则必须支持其他内容(例如std::vector<unsigned char>)。那时,您仅限于max_size() 元素(18446744073709551615 用于unsigned char 的向量),即使在那里,只有内存管理器可以找到这么大的孔。最后,WIN32 宏与这些没有任何关系

标签: c++ arrays 64-bit large-data


【解决方案1】:

让我先正确回答问题,以便其他人可以轻松获得信息。 所有三个操作都是必要的。单独一两个都不行。

  1. 将项目类型从“Win32 控制台”更改为“C++/CLR 控制台”
  2. WhozCraig 所示更改数组定义
  3. 更改项目属性,链接器 |系统 | EnableLargeAddresses 是 (/LARGEADDRESSAWARE)

现在让我们提到一些 cmets:

“为 x64 架构编译程序,而不是 x32”**

我明确表示它是作为 x64 版本编译的,Win32 方面可能会胜出。

如果在栈上分配就不行了。

它作为全局变量在堆上分配,但我也说过我尝试使用new 分配它,这也会分配给堆。

你的机器有多少内存?

真的。我的 8GB RAM 对于应用程序来说有点弱,但不会给出编译器错误,并且足以运行分配给它的 4GB 的程序。

可能重复……

不,有一些非常古老的问题并不十分相关。

内存映射文件(Thomas Matthews)

一个非常好的主意。谢谢。

关于这个问题的 6 票否决,说真的。大多数评论者甚至似乎都没有理解这个问题,更不用说解决方案了。无论/LARGEADDRESSAWARE 开关和x64 编译如何,标准C 数组似乎都由有符号整数(32 位)索引。

再次感谢 WhozCraigThomas Matthews 帮助我解决问题。

#include <vector>
typedef unsigned long long U64;
const U64 MAX_SIZE = 3*((U64)INT_MAX);
std::vector<unsigned char>prime(MAX_SIZE);
// The prime vector is then accessed in the usual way, prime[bigAddress]

我还在项目设置中关闭了 Unicode 支持,因为这可能会使字符长 2 个字节。

程序现在在具有 32GB ECC RAM 的 Xeon 工作站上运行。

6GB根据任务管理器分配给进程。

【讨论】:

  • I explicitly stated that it was compiled as x64 release 那么您的设置存在一些问题,因为 /LARGEADDRESSAWARE 默认为 64 位构建启用,并且可以使用完整的 64 位地址范围没有任何变化。您甚至阅读过/LARGEADDRESSAWARE 的文档吗?但这通常是您的算法存在缺陷的问题,这在初学者中很常见。更改为正确的解决方案,例如分而治之、动态规划或稀疏数组...
  • It was allocated on the heap as a global variable 没有这样的东西。全局变量在编译时分配在单独的部分中,堆内存在运行时通过 malloc 或 new 分配。 Standard C arrays seem to be indexed by signed ints 不,问题不在于 C 中的指针被签名(它是 neither signed nor unsigned,您将使用 (u)intptr_t 来决定签名),...
  • ...只是一些程序使用storing the tag的地址的高位,因为他们意识到Windows以2:2的比例分割用户:内核内存,从而释放出 1 位。这不是一个好方法,因为there are more low free bits 更安全,但这是糟糕的程序员所做的,当 MS 引入 3:1 拆分时,MS 只能添加标志,以便它们仅在标志已设置
  • 另一个不正确的信息是 Unicode 支持使字符长度为 2 字节char 在 C 和 C++ 中总是 1 个字节,1 个字符包含 CHAR_BIT 位,其中 CHAR_BIT == 8 在 Windows 和 POSIX 中。在 Windows 中,只有 wchar_t 是 2 字节类型。关闭 Unicode 标志只会让您默认使用 ANSI API(其中包含各种限制)并阻止您使用推荐的 API(至少很容易)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
  • 2016-08-17
  • 1970-01-01
相关资源
最近更新 更多