2012-02-09 6 views
2

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

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

мой вопрос

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

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

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

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

, например:

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

и

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

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

ответ

5

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

3

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

+0

ya Я знаю это, но мой вопрос другой – haris

+0

@haris: So Your Q is? –

+0

есть ли другая разница между ними? – haris

7

calloc заполняет память с помощью ZERO.

p=calloc(n, m); 

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

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

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

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

+0

так что кроме инициализации до нуля нет другой разницы между этими двумя? – haris

+0

как я уже сказал, память мудрая, они эквивалентны. – vulkanino

+0

Эквивалентность не 100% по двум причинам. Во-первых, есть переполнение переполнения 'n * m'. 'calloc' не будет работать, если продукт слишком велик,' malloc' просто выделяет меньше. Во-вторых, 'calloc' может быть быстрее, чем' malloc' + 'memset' (но медленнее, чем просто' malloc'). – ugoren

3

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

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

+1

: можете ли вы уточнить вторую часть – haris

+1

Я не думаю, что вторая часть права, по крайней мере, не на любой современной ОС с защищенной памятью, такой как Linux/Unix/Windows. Вы можете объяснить, что вы имеете в виду на всякий случай, если я неправильно понимаю что-то? – Jason

+0

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

3

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

ptr = malloc(num*size); 

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

+0

+1 Очень верно, спасибо за добавление этой информации ... – Jason

0

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

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

Смежные вопросы