Какое ограничение на параметр 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 явно потерпит неудачу.

Другие вопросы по тегам