Какое ограничение на параметр malloc типа size_t в C? Документы говорят, что у него есть верхний предел UINT_MAX, но я не могу выйти за пределы INT_MAX
Я хочу выделить массив 2.9GB с
database = (char*) malloc((2900 * 1000000 * sizeof(char)));
Это дает целочисленное предупреждение о переполнении и malloc
возвращается NULL
,malloc
параметр имеет тип size_t
который согласно документации имеет тип unsigned int
,
Так что максимум должен быть UINT_MAX
что по крайней мере 2,9 ГБ. Однако, если я попытаюсь выделить больше MAX_INT
malloc
выходит из строя. Это значит size_t
в моей системе типа int? Как мне это проверить? Я просмотрела
/usr/include/stdlib.h
а также
./lib/gcc/x86_64-redhat-linux/4.1.1/include/stddef.h
но не могу найти определение size_t
, Спасибо большое
3 ответа
Здесь есть два вопроса.
Во-первых, предупреждение о переполнении: оба 2900
а также 1000000
имеют тип int
поэтому результат их умножения также имеет тип int
, Результат не может быть представлен 32-разрядным целым числом со знаком, поэтому он переполняется. Вам нужно привести один (или оба) аргумента к size_t
использовать беззнаковую арифметику.
(Или вы могли бы переместить sizeof(char)
быть одним из первых двух членов, так как его тип size_t
хотя вы также можете просто удалить sizeof(char)
так как это всегда 1
.)
Во-вторых, максимальный размер, который malloc
Распределение может зависеть как от платформы, на которой вы работаете, так и от текущего состояния программы. Если для удовлетворения запроса недостаточно смежного адресного пространства, очевидно, malloc
не удастся.
Кроме того, платформа, на которой вы работаете, может иметь верхний предел размера объекта, который он может динамически размещать. Вам нужно будет обратиться к документации вашей платформы, чтобы узнать, каков этот верхний предел.
size_t
конечно нет int
, так как int
всегда подписан и size_t
всегда без знака.
Параметр имеет тип size_t
а также malloc
требуется принять любое возможное значение типа size_t
, Обратите внимание, что "принять" не означает, что требуется выделять так много; все это означает, что malloc
не допускается неверное истолкование очень большого числа, которое вы даете ему, как маленькое / отрицательное число из-за проблем переполнения, тем самым возвращая слишком маленький буфер и создавая критическую необнаружимую уязвимость, от которой ваша программа не может защититься. Есть много возможных причин malloc
не удалось выделить очень большие объекты:
- так много памяти не доступно из системы
- из-за фрагментации отсутствует непрерывный диапазон виртуальных адресов такого большого размера
- произвольные пределы
В этом случае я подозреваю, что вы можете видеть третьи, произвольные пределы, хотя я не считаю их такими произвольными. Есть очень веская причина, чтобы запретить распределение (и существование каких-либо объектов) больше SIZE_MAX/2
: взятие разницы между указателями в таких больших объектах приведет к (чрезвычайно опасному) переполнению целых чисел и неопределенному поведению, когда результат не помещается в (подписанный) тип ptrdiff_t
, Таким образом, в надежной 32-разрядной системе размер виртуального адресного пространства составляет 4 ГБ, а максимальный размер любого отдельного объекта - 2 ГБ.
Максимальный размер, который может выделить malloc, зависит как от платформы, на которой вы работаете, так и от текущего состояния программы. Если для удовлетворения запроса недостаточно смежного адресного пространства, то malloc явно потерпит неудачу.