Почему выделение памяти из 2 ^ 80 байт не прерывается?
Следующий код не генерирует исключение и печатает "успех". Почему?
#include <iostream>
int main()
{
size_t size = size_t(1024)*1024*1024*1024*1024*1024*1024*1024;
char* data = new char[size];
if (data == NULL)
std::cout << "fail" << std::endl;
else
std::cout << "success" << std::endl;
return 0;
}
- Компилятор: g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
- ОС: Ubuntu 12.04
- ОЗУ: 8 ГБ
И если это так, как это должно было работать, как я могу проверить, что у меня достаточно памяти?
[ Изменить: сделал мой глупый код немного более правильным, теперь он по крайней мере потерпит неудачу на x64, если я удалю два *1024
]
Ответы
Ответ 1
Мой компилятор может ответить на этот вопрос:
$ g++ --version
g++ (GCC) 4.7.1 20120721 (prerelease)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -Wall -Wextra -pedantic q12507456.c++
q12507456.c++: In function 'int main()':
q12507456.c++:5:42: warning: integer overflow in expression [-Woverflow]
$
Ответ 2
Скорее всего, это тот факт, что запрашиваемый вами номер слишком велик для хранения в пределах целого числа, и вы испытываете переполнение здесь, а выделенная память на самом деле намного меньше, чем вы думаете.
Здесь 2 ^ 80 = 1208925819614629174706176 согласно http://en.wikipedia.org/wiki/Yobibyte
Ответ 3
1024*1024*1024*1024*1024*1024*1024*1024
вызывает вычисление целочисленного значения, т.е. оно будет приниматься по модулю 2 ^ 32 (или 2 ^ 64, в зависимости от вашей системы) и нулевые байты, которые могут быть выделены.
Ответ 4
Помните, что в linux malloc
(который в конечном итоге поддерживает new
) может overcommit:
Начиная с версии 2.1.27 есть файл sysctl VM_OVERCOMMIT_MEMORY
и proc /proc/sys/vm/overcommit _memory со значениями 1: overcommit и 0 (по умолчанию): do not.
malloc
будет успешным и зарезервировать VA, но не будет поддерживать его со страницами. При доступе к странице может или не удастся ее совершить. OOM Killer может работать. ЕСЛИ все сбой, вы получите GPF при доступе.
Мнения делятся, является ли это поведение сумасшедшим (здоровые люди находятся в этом лагере) или блестящие (сумасшедшие люди находятся в этом лагере).
Ответ 5
Возможно, вы знаете следующее, но я изложу его только для разъяснения. Исключением не бросается буквально, код проверяется операторами if. Независимо от того, какую терминологию и методы вы используете для своего теста, есть более важное замечание, чтобы принять к сведению. Ваша система содержит максимальное значение для целых чисел, а С++ учитывает это во время компиляции, делая проверки и ведет себя соответствующим образом. Еще раз, вы тоже можете это знать. Я предполагаю, что значение либо вернется к 0, то к избыточной сумме, либо к тому, что значение, которое было там до того, как указатель начал указывать на него, остался неповрежденным (скорее всего). В этом случае указатель не будет NULL
. Попробуйте дать объявление NULL
после объявления, затем выделите память и посмотрите погоду или не передайте свои операторы if.