Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Новый оператор (как и malloc) не может выделить ~ 450 МБ памяти

Автор вопроса: Fy ZnОтветов: 1

Я работаю над программой, которая хранит в памяти массив из примерно 220 миллионов коротких значений. Этот блок данных распределяется следующим образом:

short * arrayName = new short[SIZE_OF_ARRAY];

Затем содержимое файла считывается в память. После большого масштабного обновления общей архитектуры программы другим человеком в команде именно эта строка начала вызывать сбой программы. Сообщение такое:

Microsoft Visual C++ Runtime Library
Runtime Error!
abnormal program termination

Это происходит сразу же при этом вызове выделения памяти (дальнейшие строки, такие как проверка, является ли указатель NULL, не выполняются). Даже через несколько дней нам неясно, какое именно изменение в другом коде привело к тому, что эта строка начала вести себя таким образом (на самом деле ничего, что даже отдаленно связано с этим массивом, не изменилось).

В Linux (точнее, в Ubuntu) все работает нормально; эта проблема существует только на машинах Windows. В 64-разрядных ОС Windows помогает этот обходной путь (в файле .pro):

QMAKE_LFLAGS_WINDOWS += /LARGEADDRESSAWARE

На 32-битной не помогает.

Замена строки на malloc следующим образом позволила мне проверить, является ли указатель NULL после нее (что так и есть), и получить код ошибки из errno, который равен 12 (ENOMEM) = "Недостаточно памяти".

short * arrayName = (short *)malloc(SIZE_OF_ARRAY * sizeof(short));

Этот StackOverflow вопрос кажется о той же проблеме; схожесть ее есть даже вплоть до того, что выделение меньшего объема памяти работает (а вот 450 Мб нет). Ответы там предполагали высокую фрагментацию памяти и то, что new / malloc не может выделить непрерывную область памяти, но в моем случае проблема сохраняется даже после перезагрузки, когда только ~ 600 МБ из 2 физических ГБ (и 4 виртуальных ГБ) были используется, поэтому это несколько исключено (к тому же, как я уже упоминал, точно такая же строка кода работала раньше).

Мое главное подозрение заключается в том, что это как-то связано с размером кучи (хотя я не уверен, что new и malloc выделяют память для кучи, а также я еще не нашел способ изменить размер кучи в Qt). Я что-то упустил здесь?

  • Какой компилятор вы используете? Kornel Kisielewicz 12.08.2013
  • И new, и malloc резервируют память в куче. Ненормальное завершение вашей программы, скорее всего, является необработанным исключением bad_alloc. Greenflow 12.08.2013
  • @KornelKisielewicz, MSVC2010. Fy Zn 12.08.2013
  • Вы пытались разрезать дерево пополам, чтобы увидеть, какое изменение вызвало эту ошибку? greatwolf 12.08.2013
  • @greatwolf, да, как я уже сказал, точная фиксация была обнаружена, но она включает изменения во многих файлах и во многих местах в архитектуре программы, которые все взаимосвязаны. Невозможно отменить их один за другим. Fy Zn 12.08.2013
  • И кстати... возможно, что у вас закончилась память. 32-битная Windows довольно ограничена, когда речь идет об использовании памяти. Откройте монитор ресурсов и следите за использованием памяти. Greenflow 12.08.2013

c++qtmemorynew-operatormalloc

Ответы

Ответ 1 · рейтинг 2 · MSalters

Выделение памяти не выполняется из-за нехватки адресного пространства, а не из-за нехватки оперативной памяти. Недостаток оперативной памяти приводит к замедлению работы программ и большому количеству перегрузок диска, поскольку программы выгружаются на диск.

/LARGEADDRESSAWARE сообщает ОС, что ваше приложение может принимать большее адресное пространство. Win64 предоставит приложениям Win32 3 ГБ адресного пространства, в Win32 это не является стандартом.

Отключение ASLR может помочь, поскольку оно будет загружать библиотеки DLL линейным образом (таким образом, с предсказуемыми смещениями, что является угрозой безопасности). С ASLR библиотеки DLL разбросаны по памяти. Поскольку всего 10 DLL разбросаны по 2 ГБ адресного пространства (а это нереально мало), среднее пространство между ними составляет ~ 200 МБ.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы