Разница между malloc и calloc?

вы могли бы использовать exec или eval для выполнения кода python в виде строки. здесь здесь , здесь и здесь

718
задан Mat 25 August 2013 в 17:40
поделиться

4 ответа

calloc () инициализирует буфер нулями, в то время как malloc () оставляет память неинициализированной.

EDIT:

Обнуление памяти может займет немного времени, поэтому вы, вероятно, захотите использовать malloc () , если производительность является проблемой. Если инициализация памяти более важна, используйте calloc () . Например, calloc () может сохранить вам вызов memset () .

813
ответ дан 22 November 2019 в 21:28
поделиться

Менее известное различие заключается в том, что в операционных системах с оптимистичным распределением памяти, таких как Linux, указатель, возвращаемый malloc , не поддерживается реальной памятью, пока программа не коснется это.

calloc действительно касается памяти (записывает в нее нули), и, таким образом, вы можете быть уверены, что ОС поддерживает выделение фактической оперативной памятью (или подкачкой). По этой же причине он медленнее, чем malloc (он не только должен его обнулить, ОС также должна найти подходящую область памяти, возможно, заменив другие процессы)

См., Например, этот вопрос SO для дальнейшего обсуждения поведения malloc

355
ответ дан 22 November 2019 в 21:28
поделиться

Нет никакой разницы в размере выделенного блока памяти. calloc просто заполняет блок памяти физическим шаблоном с нулевыми битами. На практике часто предполагается, что объекты, расположенные в блоке памяти, выделенном с помощью calloc , имеют начальное значение, как если бы они были инициализированы литералом 0 , то есть целые числа должны иметь значение 0 , переменные с плавающей запятой - значение 0,0 , указатели - соответствующее значение нулевого указателя, и т. д.

Однако с педантичной точки зрения calloc (а также memset (..., 0, ...) ) гарантированно только правильно инициализировать (нулями) объекты типа unsigned char . Не гарантируется, что все остальное будет правильно инициализировано и может содержать так называемое представление ловушки , которое вызывает неопределенное поведение. Другими словами, для любого типа, отличного от unsigned char , вышеупомянутый шаблон с нулевыми битами может представлять недопустимое значение, представление ловушки.

Позже, в одном из технических исправлений к стандарту C99, поведение было определено для всех целочисленных типов (что имеет смысл). То есть формально в текущем языке C можно инициализировать только целочисленные типы с помощью calloc memset (..., 0, ...) ). Использование его для инициализации чего-либо еще в общем случае приводит к неопределенному поведению с точки зрения языка C.

На практике calloc работает, как мы все знаем :), но если бы вы хотите использовать это (учитывая вышесказанное) зависит от вас. Я лично предпочитаю избегать этого полностью, вместо этого использую malloc и выполняю свою собственную инициализацию.

Наконец, еще одна важная деталь заключается в том, что calloc требуется для расчета окончательного размера блока ] внутренне , путем умножения размера элемента на количество элементов. При этом calloc должен следить за возможным арифметическим переполнением. Это приведет к неудачному распределению (нулевой указатель), если запрошенный размер блока не может быть правильно рассчитан. Между тем, ваша версия malloc не пытается следить за переполнением. В случае переполнения он выделит некоторый «непредсказуемый» объем памяти.

26
ответ дан 22 November 2019 в 21:28
поделиться

Одно часто упускаемое из виду преимущество calloc заключается в том, что (соответствующие реализации) он помогает защитить вы против уязвимостей целочисленного переполнения. Сравните:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

vs.

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

Первый может привести к крошечному выделению и последующим переполнениям буфера, если count больше, чем SIZE_MAX / sizeof * bar . Последний в этом случае автоматически выйдет из строя, так как объект такого размера не может быть создан.

Конечно, вам, возможно, придется следить за несовместимыми реализациями, которые просто игнорируют возможность переполнения ... Если это проблема на целевых платформах, вам все равно придется вручную проверить переполнение .

105
ответ дан 22 November 2019 в 21:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: