Выделение памяти в C ++: «new» выбрасывает bad_alloc? - PullRequest
2 голосов
/ 09 ноября 2010

В моем приложении я сохраняю воксельные данные (сжатый байтовый массив) и пытаюсь снова загрузить их в память.

Но мое приложение вылетает на машине с Windows 7 (64 бит, 12 ГБ), давая bad_alloc.

Это прекрасно работает в Linux и даже работает на некоторых других машинах Windows 7 с 4 ГБ памяти.

Размер сжатого байта составляет около 200 МБ, а размер несжатого байта - около 300 МБ (так что всего 500МБ зарезервировано до этого «нового» оператора, что оставляет почти 8 ГБ без учета системной памяти).До этого я не выполнял никаких других основных этапов выделения памяти, поэтому не думаю, что память фрагментирована.Я пользуюсь 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 ]

3 голосов
/ 09 ноября 2010

Если вы собираете программу как 32-разрядный двоичный файл в Windows, вы получаете только 2 ГБ доступного адресного пространства (верхняя половина зарезервирована).

Если вы считаете, что адресное пространство может быть фрагментированоиз-за того, что выделяется много разных вещей (загружаются библиотеки DLL, стеки потоков, динамическое выделение), вполне вероятно, что в результате большие выделения завершатся очень быстро.

Вы можете попробовать дать компоновщику /LARGEADDRESSAWAREфлаг, который даст вам 3 ГБ адресного пространства в правильно настроенной 32-битной Windows и полное 4 ГБ адресного пространства в 64-битной Windows.На самом деле, хорошая идея - найти способ переопределить вашу программу, чтобы вы могли использовать несколько меньших выделений вместо одного огромного.

1 голос
/ 09 ноября 2010

При очень больших выделениях вы можете столкнуться с проблемами фрагментации: в куче может быть, скажем, 600 МБ памяти, но она разбита на куски по 100 МБ, поэтому вы не можете выделить один блок по 500 МБ. Некоторые реализации new (которые в большинстве случаев на самом деле вызывают malloc()) не очень умны, чтобы избежать изящных ошибок, когда это происходит.

При таком большом распределении вам, возможно, повезет больше, если использовать функции для ОС, такие как VirtualAlloc () и HeapAlloc () в Windows.

0 голосов
/ 09 ноября 2010

Если ваш размер данных фиксирован или имеет известный потолок, вы можете попробовать статическое размещение в стеке или в глобальной переменной.

...