C ++内存分配:'new'抛出bad_alloc?

时间:2010-11-09 03:11:06

标签: c++ memory-management mingw

在我的应用程序中,我保存了体素数据(压缩字节数组)并尝试将其重新加载到内存中。

但我的应用程序在Windows 7计算机(64位,12 GB)中崩溃,给出了bad_alloc。

这在Linux上运行良好,甚至可以在其他具有4 GB内存的Windows 7机器上运行。

压缩的大小约为200Mb,未压缩的字节大小约为300Mb(因此在此'new'语句之前仅保留500 MB,这使得除系统内存之外几乎留下8 GB)。在此之前我没有运行任何其他主要的内存分配步骤,所以我不认为内存是碎片化的。 我使用MinGW GCC版本4.5.0

有关此的任何提示吗?

提前感谢。

QFile fileVol(strVFile);

//Read VolumeData
fileVol.open(QIODevice::ReadOnly);
QDataStream volstream(&fileVol);
QByteArray volCmprsdByteArray;     //This holds the compressed byte array

//Read some additional information
int nx, ny, nz, bbp;
int voltype;
volstream >> nx;
volstream >> ny;
volstream >> nz;
volstream >> bbp;
volstream >> voltype;
volstream >> volCmprsdByteArray;     //read our compressed voxel-data

//we have original uncompressed pixel data
QByteArray volUncmprsdByeArray = qUncompress(volCmprsdByteArray);

int uncompressedSize = volUncmprsdByeArray.size(); // size of the byte array
qDebug("new char for uncompressed data size %d",uncompressedSize);

unsigned char* volumeData=NULL;

//Trying to allocate new memory 
try {
    // ##### breaks here.   ####
    volumeData =new unsigned char[uncompressedSize];   
 }
catch (std::bad_alloc e)
 {
      cout << "lu_solver() bad_alloc: " << e.what() << endl;
      cout << "Size " << uncompressedSize << endl;
      //return;
}

3 个答案:

答案 0 :(得分:3)

如果您在Windows上将程序构建为32位二进制文​​件,则只能获得2GB的可用地址空间(上半部分是保留的)。

如果你认为地址空间可以通过分配大量不同的东西(DLL加载,线程堆栈,动态分配)来分段,那么很可能你最终会很快失败。

您可以尝试为链接器提供/LARGEADDRESSAWARE标志,这将在正确配置的32位Windows上为您提供3GB的地址空间,在64位Windows上提供完整的4GB地址空间。但是,真的,找到重新实现程序的方法是个好主意,这样你就可以使用几个较小的分配而不是一个较大的分配。

答案 1 :(得分:1)

对于非常大的分配,您可能会遇到碎片问题:例如,堆可能有600mb的内存,但是切换为100mb的块,因此您无法分配单个500mb块。 new(在大多数情况下真正调用malloc())的某些实现对于发生这种情况时优雅地失败并不是很明智。

通过如此大的分配,您可以在Windows上使用特定于操作系统的功能,例如VirtualAlloc()HeapAlloc()

答案 2 :(得分:0)

如果您的数据大小是固定的,或具有已知的上限,您可以尝试在堆栈或全局变量中进行静态分配。