Почему new [-1] генерирует segfault, а new [-2] выбрасывает bad_alloc? - PullRequest
12 голосов
/ 13 марта 2012

Я попытался проверить исключение bad_alloc, передав несколько отрицательных аргументов new[].При прохождении небольших отрицательных чисел я получаю то, на что рассчитываю - bad_alloc.Однако, передавая -1, я вижу, что мой объект создается тысячи раз (я печатаю статический счетчик в конструкторе), и приложение завершается с segfault.

new[] преобразует целое число со знаком в size_t, поэтому -1 - это максимум size_t, а -2 - это maximum - 1 и т. Д.

Так почему new[] выдает исключение при получении какого-то огромного числа, но пытается выделить при получении максимум size_t?В чем разница между 1111...1 и 1111...0 для new[]?:)

Заранее спасибо!

1 Ответ

17 голосов
/ 13 марта 2012

Вот мое дикое предположение:

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

Давайте предположим, что size_t - это 32-разрядный код.Скомпилировано для 32-бит.


Когда вы делаете:

int *array = new int[-1];

-1 становится -1 * 4 bytes = 4294967292 (после переполнения).Но если реализация распределителя помещает 4 байта метаданных рядом с выделенной областью.Фактический размер становится следующим:

4294967292 + 4 bytes = 0 bytes (after overflow)

Таким образом, фактически выделяется 0 байт.

Когда вы пытаетесь получить доступ к памяти, у вас возникает ошибка, так как вы выходите за пределынемедленно.


Теперь предположим, что вы делаете:

int *array = new int[-2];

-2 становится -2 * 4 bytes = 4294967288 (после переполнения).Добавьте 4 байта метаданных, и вы получите 4294967288 + 4 = 4294967292.

Когда распределитель запрашивает 4294967292 байтов от ОС, он отклоняется.Таким образом, он выдает bad_alloc.


Таким образом, в принципе, возможно, что -1 и -2 имеют значение между тем, будет ли он переполняться после того, как распределитель добавит свои метаданные.

...