2010-11-09 5 views
2

В моем приложении я сохраняю voxel-data (сжатый массив байтов) и пытается загрузить его обратно в память.Распределение памяти на C++: «новый» выбрасывает bad_alloc?

Но мое приложение аварийно завершает работу в 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; 
} 
+2

Вы строите это как 32-битный двоичный или 64-битный двоичный файл? –

+0

О, я использую CMake, и я havent указал, какой buildtype.I использовать библиотеки LGPL QT, которые являются 32bit.and в Диспетчере задач, он показывает мое приложение как * 32 бит. Поэтому я думаю, его 32-битная сборка. –

+0

У вас уже есть несжатые данные, зачем выделять их снова? Кроме того, попробуйте спать в 'catch' и проверьте использование памяти в окнах. – ruslik

ответ

3

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

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

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

+0

Единственная проблема заключается в том, что 3GB swith не будет работать ни на одной версии окон. – ruslik

+0

@ ruslik: Верно. Следовательно, «правильно настроенная 32-разрядная Windows» (я полагаю, что читатели могут искать '/ LARGEADDRESSAWARE', чтобы узнать, какая конфигурация требуется, с моей головы я помню, что ОС нужно загружать с помощью'/3GB 'switch, но я не могу вспомнить, требуется ли другая конфигурация). –

+0

спасибо за ответ. Мне жаль, я родом из фона Java, и эта память для меня совершенно новая. Это означает, что 32-битные приложения могут получить доступ только к 2 ГБ памяти максимум? –

0

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

1

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

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

+0

спасибо за ответ. Но мое приложение должно быть мультиплатформенным. –

Смежные вопросы