Ответ 1
Здесь мое дикое предположение:
Во множестве реализаций распределитель разместит некоторые метаданные рядом с выделенной областью.
(Например, размер выделения.) Таким образом, вы фактически выделяете больше, чем вы просили.
Предположим, что size_t
- 32 бит. Скомпилирован для 32-разрядных.
Когда вы выполните:
int *array = new int[-1];
-1
становится -1 * 4 bytes = 4294967292
(после переполнения). Но если реализация распределителя помещает 4 байта метаданных рядом с выделенной областью. Фактический размер будет:
4294967292 + 4 bytes = 0 bytes (after overflow)
Таким образом, фактически выделяется 0
байт.
Когда вы пытаетесь получить доступ к памяти, вы segfault, так как сразу выходите за пределы.
Теперь скажите, что вы делаете:
int *array = new int[-2];
-2
становится -2 * 4 bytes = 4294967288
(после переполнения). Добавьте 4 байта метаданных и получите 4294967288 + 4 = 4294967292
.
Когда распределитель запрашивает 4294967292
байты из ОС, он отказывается. Поэтому он бросает bad_alloc
.
В принципе, возможно, что -1
и -2
делает разницу между тем, будет ли он переполняться после того, как распределитель добавит свои метаданные.