C++ C++;内存分配:';新';扔坏东西?

C++ C++;内存分配:';新';扔坏东西?,c++,memory-management,mingw,C++,Memory Management,Mingw,在我的应用程序中,我保存体素数据(压缩字节数组),并尝试将其重新加载到内存中 但是我的应用程序在Windows7机器(64位,12GB)上崩溃,导致错误的分配 这在Linux上运行良好,甚至可以在其他一些内存为4GB的Windows7机器上运行 压缩的字节大小约为200Mb,未压缩的字节大小约为300Mb(因此在这个“new”语句之前只保留了500MB,不包括系统内存,只保留了近8GB)。在此之前,我没有运行任何其他主要的内存分配步骤,因此我不认为内存是碎片化的。 我使用的是mingwgcc4.

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

但是我的应用程序在Windows7机器(64位,12GB)上崩溃,导致错误的分配

这在Linux上运行良好,甚至可以在其他一些内存为4GB的Windows7机器上运行

压缩的字节大小约为200Mb,未压缩的字节大小约为300Mb(因此在这个“new”语句之前只保留了500MB,不包括系统内存,只保留了近8GB)。在此之前,我没有运行任何其他主要的内存分配步骤,因此我不认为内存是碎片化的。 我使用的是
mingwgcc
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;
}
QFile文件卷(strVFile);
//读卷数据
fileVol.open(QIODevice::ReadOnly);
QDataStream-volstream(&fileVol);
QByteArray volCmprsdByteArray//它保存压缩字节数组
//阅读一些附加信息
纽约州、新西兰州、bbp国际机场;
int型;
volstream>>nx;
volstream>>纽约;
volstream>>新西兰;
volstream>>bbp;
volstream>>电压型;
volstream>>volCmprsdByteArray//读取压缩的体素数据
//我们有原始的未压缩像素数据
QByteArray voluncmprsdbyarray=qncompress(volcmprsdbyterray);
int uncompressedSize=voluncmpsdbyearray.size();//字节数组的大小
qDebug(“未压缩数据大小%d的新字符”,未压缩大小);
无符号字符*volumeData=NULL;
//正在尝试分配新内存
试一试{
//在这里休息####
volumeData=新的无符号字符[uncompressedSize];
}
捕获(标准:错误分配)
{

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

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

当你考虑地址空间可以被许多不同的事物分割(DLL被加载,线程栈,动态分配)时,很可能最终会有很大的分配失败,很快。


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

对于非常大的分配,您可能会遇到碎片问题:堆可能会剩下600mb的内存,但会被分割成100mb的块,因此您无法分配单个500mb的块。
new
的一些实现(在大多数情况下真正调用
malloc()
)当这种情况发生时,你不会很聪明地优雅地失败


有了如此大的分配,您可能会更幸运地使用操作系统特定的函数,如Windows上的和。

您是将其构建为32位二进制还是64位二进制?哦,我使用CMake,但我没有指定构建类型。我使用32位的LGPL QT库。在任务管理器中,它将我的应用程序显示为*32位。因此我猜它的32位构建类型是ld.您已经有未压缩的数据,为什么要重新分配?另外,请尝试在
catch
中睡眠,并检查windows分配的内存使用情况。唯一的问题是3GB swith无法在任何版本的windows上工作。@ruslik:对。因此“正确配置的32位windows”(我假设读者可以查找
/largeaddressware
来发现需要什么配置;我记得操作系统必须使用
/3GB
开关启动,但我不记得是否需要其他配置)。谢谢你的回答。很抱歉,我来自Java背景,这种内存对我来说是全新的。这是否意味着32位应用程序最多只能访问2Gb的内存?通过使用
VirtualAlloc
MEM\u TOP\u DOWN
来确定顶部,通过编程也很容易检测
/3GB
开关是否设置了地址空间的一部分。@umanga:每个32位程序都有4GB的地址空间(32位的意思)。但是,操作系统需要保留部分地址空间供系统使用。在32位窗口上,默认情况下,整个地址空间的上半部分都被保留,留给您2GB的空间。在64位窗口上,情况相同(请记住,即使操作系统是64位的,进程仍然是32位的),除非您设置
/largeaddressware
标志,在这种情况下,您可以获得所有4GB的地址空间。就我所知,在Linux上,您可以获得3GB的地址空间(虽然我不知道;我不是为Linux开发的)。谢谢您的回答。但我的应用程序应该是多平台的。