【问题标题】:Allocating a large array in C++Builder在 C++Builder 中分配一个大数组
【发布时间】:2017-03-16 01:42:51
【问题描述】:

我在 Borland C++Builder 6 中工作,必须创建一个 13230 x 26460 的 double 值数组。

此矩阵大小包含350065800 元素,并占用350065800 * 8 bytes = 2800526400 bytes = 2.6GB 内存。

我使用的是 8GB RAM 的 64 位 Windows。

即使我在图像标志选项(GF)中设置LARGEADDRESSAWARE标志,它也不能声明数组。

还有其他方法可以在 Borland C++Builder 中声明 2.6GB 大小的数组吗?

【问题讨论】:

  • 在堆上创建。但是您可能会发现 2GB 是系统不会轻易让您超过的硬限制。或者,创建一个数组数组。

标签: c++builder c++builder-6


【解决方案1】:

您不能在 BCB6 中将 8 GByte 作为单个数组!!!!这有几个原因:

  1. 您的目标是 32 位应用程序

    因此您的操作系统或模拟器无法处理超过 2 或 4 GB 的内存。这意味着无论您做什么,8GB 都是毫无疑问的。是的,即使你有 x64 Windows 操作系统,你的 32 位应用程序也在 WoW64 模拟器中运行......

  2. Borland 分配 new 无法分配超过 1 GB 的单个块

    不知道为什么限制应该接近 2 或 4 GB,但至少对我来说略高于 1GB(即使有超过 2GB 的免费内存 WoW64)是安全的最大限制分配。可能继承了旧版本的 Borland 内存管理器的限制。此行为在 BDS2006 上进行了测试,因此不确定 BCB6 是否相同,但我认为没有理由不应该这样做,因为它们共享相同的内存管理器和相关的 C++ 引擎错误(不存在于 BCB5 顺便说一句)。

最后,当您使用new,delete[] 时,您应该检查一下(只是为了确定):

所以你需要把你的数组分成更多的块。当您获得 2D 矩阵时,您可以按照 Malcolm McLean 的建议使用数组数组。所以如果你数组的单元格是T 试试:

#define T double
T **m=new T*[13230];
for (int i=0;i<13230;i++) m[i]=new T[26460];

m[10000][20000]=1.2345; // do your stuff with m[][]

for (int i=0;i<13230;i++) delete[] m[i];
delete[] m;

只需更改您的数据类型T(我使用double,因为它也是8字节)并添加检查new返回NULL

如果您真的需要 8GB 矩阵,则需要将其存储在 FILE 中。或者使用 RAD2009 或更新版本的 64 位编译器。

【讨论】:

  • C++Builder 6 和 BDS 2006 请勿 默认使用相同的内存管理器。 BDS 2006 是switch to FastMM as the default memory manager 的第一个版本(现在仍然是默认管理器),而不是旧的 BorlandMM 内存管理器(不过,您可以在 BCB6 中使用 FastMM。我愿意)。并且 Win64 支持未添加到 C++Builder until RAD Studio XE3(RAD Studio 2009 之后的 4 个版本)。
  • @RemyLebeau 问题是它们是否与我在 BDS2006 中通过添加默认构造函数修复的错误相关...修复了其他用户在 BCB6 中遇到的一些问题(我不使用它)。因此它们要么是相关的,要么是由 C++ 引擎和/或编译器引起的错误,并且仅屏蔽为内存冲突。我对 Borland 内部没有足够的背景知识,所以我只能推测。
【解决方案2】:

正如 Remy 所说,C++ Builder 6 只能创建 32 位应用程序,该应用程序最多能够消耗 2GB(如果你欺骗了 32 位操作系统,则为 3GB)内存。此外,通常消耗 8GB 内存并不被认​​为是良好的编程习惯。
话虽如此,如果您绝对必须这样做,您可以使用 CreateFileMappingMapViewOfFile 创建一个现金内存。这样,您的数据就存在于磁盘上,但您可以像访问内存一样访问它。缺点是会很慢。

HANDLE hFile = ::CreateFile(fileName, ...);
HANDLE hFM = ::CreateFileMapping(hFile, ...);
double**m= (double**)::MapViewOfFile(hFM, ...);
m[10000][20000]=1.2345; // do your stuff with m[][]
::UnmapViewOfFile((void*)m); 
::CloseHandle(hFM);
::CloseHandle(hFile);

不要忘记使用UnmapViewOfFileCloseHandle 进行清理。如果你不这样做,你可能会弄乱 Windows 的内存。

【讨论】:

  • 顺便确保 hFile 有足够的空间来保存所有数据。在调用 CreateFileMapping 之前,您可以调用 SetFilePointer 将文件增大到足以容纳所有数据的大小。
猜你喜欢
  • 1970-01-01
  • 2018-06-22
  • 2020-01-05
  • 2017-06-26
  • 1970-01-01
  • 1970-01-01
  • 2019-02-24
  • 2017-09-28
相关资源
最近更新 更多