1

据我所知,调用malloc()基本上意味着程序正在向操作系统请求一大块内存。我正在编写一个与相机接口的程序,在该程序中我需要分配足够大的内存块以一次存储数百张图像(它是一个快速的相机)。

当我为大约 1.9 Gb 的图像分配空间时,一切正常。分配计算非常简单:

int   allocateBurst( int numImages ) 
{
    int streamSize = ZIMAGESIZE * numImages; 
    data.images = new unsigned short [streamSize];
    return 0; 
}

但是一旦超过 2 Gb 限制,我就会收到如下运行时错误:

terminate called after throwing an instance of 'std::bad_alloc'
    what():  std::bad_alloc

似乎 2 Gigs 可能是我一次可以分配的最大大小。我有 32 Gigs 的内存,并且希望能够在一次分配中分配更大的内存。这可能吗?

我正在运行 Ubuntu 12.10。

4

3 回答 3

1

可能存在操作系统无法授予您大内存分配的潜在问题,因为它正在为其他应用程序使用内存。检查您的操作系统以查看限制是什么。

还知道某些操作系统会将内存“分页”到硬盘。当您的程序请求页面外的内存时,操作系统将与硬盘交换页面。知道了这一点,我推荐一种经典的“双缓冲”或“多缓冲”技术。

您至少需要两个线程:阅读和写作。一个线程负责从相机读取数据并放入缓冲区。当它填满一个缓冲区时,它会从另一个缓冲区开始。同时,写入线程从缓冲区开始并将其写入磁盘(块文件写入)。当写入线程完成一个缓冲区时,它会从下一个缓冲区开始。缓冲区应按循环顺序重复使用。

神奇的是要有足够的缓冲区,这样读者就永远赶不上写者了。

由于您使用了几个小缓冲区,因此您不应该从操作系统中得到任何错误。

有一些方法可以对此进行优化,例如从操作系统获取静态缓冲区。

于 2013-05-27T17:59:59.137 回答
1

问题是您使用带符号的 32 位变量来描述无符号的 64 位数字。

使用“size_t”而不是“int”来保存存储计数。这与您打算存储的内容无关,而与您需要多少数量无关。

#include <iostream>

int main(int /*argc*/, const char** /*argv*/)
{
  int units = 2;

  // 32-bit signed, i.e. 31-bit numbers.
  int intSize = units * 1024 * 1024 * 1024;

  // 64-bit values (ULL suffix)
  size_t sizetSize = units * 1024ULL * 1024ULL * 1024ULL;

  std::cout << "intSize = " << intSize << ", sizetSize = " << sizetSize << std::endl;

  try {
    unsigned short* intAlloc = new unsigned short[intSize];
    std::cout << "intAlloc = " << intAlloc << std::endl;
    delete [] intAlloc;
  } catch (std::bad_alloc) {
    std::cout << "intAlloc failed (std::bad_alloc)" << std::endl;
  }

  try {
    unsigned short* sizetAlloc = new unsigned short[sizetSize];
    std::cout << "sizetAlloc = " << sizetAlloc << std::endl;
    delete [] sizetAlloc;
  } catch (std::bad_alloc) {
    std::cout << "sizetAlloc failed (std::bad_alloc)" << std::endl;
  }

  return 0;
}

输出(g++ -m64 -o test test.cpp 在 Mint 15 64 位下使用 g++ 4.7.3 在具有 4Gb 内存的虚拟机上)

intSize = -2147483648,sizetSize = 2147483648
intAlloc 失败
sizetAlloc = 0x7f55affff010
于 2013-05-27T19:37:26.457 回答
-2
int   allocateBurst( int numImages ) 
{
    // change that from int to long
    long streamSize = ZIMAGESIZE * numImages; 
    data.images = new unsigned short [streamSize];
    return 0; 
}

尝试使用

long

或者

将 allocateBurst 函数的结果转换为“uint_64”,并将函数的返回类型转换为 uint_64

因为 int 您分配 32 位分配,而 long 或 uint_64 分配 64 位分配,这可能会为您分配更多内存空间。

希望有帮助

于 2013-05-27T17:52:07.113 回答