Почему выделение памяти из 2 ^ 80 байт не прерывается? - программирование

Почему выделение памяти из 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]

4b9b3361

Ответ 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.