malloc и calloc

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

я знаю, что calloc инициирует блок памяти, здесь мой вопрос не фокусируется на этой части.

мой вопрос

определение malloc говорит, что он выделяет блок памяти указанного размера.

а calloc сообщает, что выделяет несколько блоков памяти одинакового размера.

Является ли выделение одного блока памяти и нескольких блоков памяти реальной разницей между ними?

потому что я чувствую, что мы можем сделать то же самое с помощью malloc, что можно сделать с помощью calloc.

Например :

int *ptr;
ptr=(int *) malloc(100 * (sizeof(int)));

и

int *ptr;
ptr=(int *) calloc(100,sizeof(int));

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


person haris    schedule 09.02.2012    source источник


Ответы (7)


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

person Jason    schedule 09.02.2012

calloc заполняет память нулями.

p=calloc(n, m); 

эквивалентно

p=malloc(n*m); 
memset(p, 0, m * n);

Таким образом, если вы намереваетесь обнулить выделенную память, то при использовании malloc вам нужно вычислить n*m дважды или использовать временную переменную, что и делает calloc.

Изменить: я только что прочитал стандарт ISO C и обнаружил, что нигде не указано, что реализация calloc должна проверять, не переполняется ли n*m, то есть превышает ли оно константу SIZE_MAX в стандарте C99.

person vulkanino    schedule 09.02.2012
comment
так что кроме инициализации с нуля нет другой разницы между ними? - person haris; 09.02.2012
comment
как я уже сказал, по памяти они эквивалентны. - person vulkanino; 09.02.2012
comment
Эквивалентность не 100% по двум причинам. Во-первых, есть ловушка n*m переполнения. calloc потерпит неудачу, если продукт слишком большой, malloc просто выделите меньше. Во-вторых, calloc может быть быстрее, чем _5 _ + _ 6_ (но медленнее, чем просто malloc). - person ugoren; 09.02.2012
comment
Во-первых, согласитесь. Во-вторых, я никогда не говорил обратного! - person vulkanino; 09.02.2012
comment
@urogen: я не понимаю, как malloc (n) - или какой-либо другой распределитель - может выделить меньше, чем 'n' байтов ?? если он не может выделить запрошенную сумму, он должен просто потерпеть неудачу - person kaiwan; 07.02.2018

Да, основное различие упомянуто выше. Также calloc () медленнее, чем malloc () с точки зрения распределения памяти операционной системы.

Указатель возврата malloc () не касается реальной памяти, пока программа не коснется malloc (). В то время как calloc () возвращает память с ОЗУ.

person Sunil Bojanapally    schedule 09.02.2012
comment
: вы можете уточнить вторую часть - person haris; 09.02.2012
comment
Я не думаю, что вторая часть верна, по крайней мере, не для любой современной ОС с защищенной памятью, такой как Linux / Unix / Windows ... не могли бы вы объяснить, что вы имеете в виду, на случай, если я что-то неправильно понимаю? - person Jason; 09.02.2012
comment
Операционные системы, такие как Linux, придерживаются оптимистической стратегии распределения памяти. Таким образом, указатель, возвращаемый malloc, не поддерживается физической памятью, пока программа не использует эту память. С точки зрения оборудования, это 2 страницы, а именно анонимные страницы и страницы с файловой поддержкой. Мы получаем анонимную страницу, когда выполняем malloc (). Анонимные страницы могут читать область подкачки, и для calloc () ОС также должна найти подходящую область памяти, возможно, заменив другие процессы, что замедляет работу. - person Sunil Bojanapally; 09.02.2012
comment
+1 Спасибо за объяснение, хотя вы можете изменить формулировку во втором абзаце, так как это немного сбивает с толку, как вы это формулируете ... возможно, вам следует прямо упомянуть Из-за оптимистичного распределения памяти на уровне ОС ... , и т.д. - person Jason; 09.02.2012

Ну calloc также инициализирует блок памяти, чтобы он содержал нули, в отличие от malloc.

person Alok Save    schedule 09.02.2012
comment
Я знаю это, но у меня другой вопрос - person haris; 09.02.2012
comment
есть ли еще какая-нибудь разница между ними? - person haris; 09.02.2012
comment
@haris: Ну, вы указали основное отличие, и в ответах здесь указано одно важное отличие, которое вы упустили. Так что нет никакой разницы, кроме этих. - person Alok Save; 09.02.2012

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

ptr = malloc(num*size);

вероятно, не даст желаемого результата (и, скорее всего, приведет к более поздней ошибке сегментации). В таких ситуациях предпочтительнее использовать calloc(num,size) (хотя вы также можете проверить переполнение перед вызовом malloc, если вас беспокоит тот факт, что calloc() инициализирует только что выделенную память нулевым значением).

person Martin Wanvik    schedule 09.02.2012

Основное различие между ними заключается в том, что calloc инициализирует блоки памяти до нуля, в то время как блоки памяти, созданные malloc, содержат значение мусора.

поэтому лучше использовать calloc вместо malloc, чтобы избежать неопределенности в вашем коде.

person Anant Barthwal    schedule 08.08.2015

=== Вы можете увидеть следующую разницу для функций mallac () и calloc () ===

Инициализация:
malloc () не очищает и не инициализирует выделенную память.
calloc () инициализирует выделенную память нулем.

Синтекс:

void *malloc(size_t size);                   // syntex for malloc() function
void *calloc(size_t num, size_t size);       // syntex for calloc() function

// example
ptr = malloc(num*size);   // for malloc() function
ptr = calloc(num,size);   // for calloc() function

Аргумент:
Если вы рассмотрите синтаксис malloc (), он будет принимать только 1 аргумент.
Если вы рассмотрите синтаксис calloc (), он будет принимать 2 аргумента.

Способ распределения памяти ::
функция malloc () назначает память желаемого «размера» из доступной кучи.
Функция calloc () назначает память, размер которой равен "число * размер".

person Majbah Habib    schedule 23.06.2019