Разница между malloc и памятью?
в чем разница между:
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
или:
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
когда это хорошая идея, чтобы использовать calloc над malloc или наоборот?
18 ответов:
calloc()
ноль-инициализирует буфер, в то время какmalloc()
оставляет память неинициализированной.EDIT:
вычеркивать из памяти может занять немного времени, так что вы, вероятно, хотите использовать
malloc()
если производительность является проблемой. Если инициализация памяти более важна, используйтеcalloc()
. Например,calloc()
может сохранить вам вызовmemset()
.
менее известная разница заключается в том, что в операционных системах с оптимистичным выделением памяти, таких как Linux, указатель возвращается
malloc
не поддерживается реальной памятью, пока программа не коснется ее.
calloc
действительно касается памяти (она записывает на нее нули), и поэтому вы будете уверены, что ОС поддерживает выделение с фактической ОЗУ (или свопом). Именно поэтому он медленнее, чем malloc (мало того, что он должен обнулить его, ОС также должна найти подходящую область памяти возможно замена других процессов)см., например,это так вопрос для дальнейшего обсуждения поведения malloc
одно часто упускаемое из виду преимущество
calloc
это (соответствующие реализации) это поможет защитить вас от целочисленных уязвимостей переполнения. Сравните:size_t count = get_int32(file); struct foo *bar = malloc(count * sizeof *bar);
и
size_t count = get_int32(file); struct foo *bar = calloc(count, sizeof *bar);
первый может привести к крошечному выделению и последующему переполнению буфера, если
count
большеSIZE_MAX/sizeof *bar
. Последний автоматически завершится неудачей в этом случае, так как объект, который большой не может быть создан.конечно, вы, возможно, придется быть начеку для несоответствующих реализаций, которые просто игнорируют возможность переполнения... Если это проблема на целевых платформах, вам все равно придется выполнить ручной тест для переполнения.
документация делает calloc похожим на malloc, который просто делает нулевую инициализацию памяти; это не основное различие! Идея calloc заключается в том, чтобы абстрагироваться от семантики копирования при записи для выделения памяти. Когда вы выделяете память с calloc, все это сопоставляется с одной и той же физической страницей, которая инициализируется до нуля. Когда какая-либо из страниц выделенной памяти записывается в физическую страницу выделяется. Это часто используется для создания огромных хэш-таблиц, например, так как части хэша пустые страницы не поддерживаются никакой дополнительной памятью (страницами); они с радостью указывают на одну страницу с нулевой инициализацией, которая может быть даже разделена между процессами.
любая запись на виртуальный адрес сопоставляется со страницей, если эта страница является нулевой страницей, выделяется другая физическая страница, нулевая страница копируется туда и поток управления возвращается клиентскому процессу. Это работает так же, как файлы с отображением памяти, виртуальная память и т. д. работа.. он использует пейджинг.
вот один история оптимизации ПО ТЕМЕ: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/
нет никакой разницы в размере выделенного блока памяти.
calloc
просто заполняет блок памяти физическим шаблоном всех нулевых битов. На практике часто предполагается, что объекты, расположенные в блоке памяти, выделяются с помощьюcalloc
имеют начальное значение, как если бы они были инициализированы литералом0
, т. е. целые числа должны иметь значение0
, переменные с плавающей запятой-значение0.0
, указатели-соответствующее значение нулевого указателя, и так далее.от педантичная точка зрения, однако,
calloc
(а такжеmemset(..., 0, ...)
) гарантируется только правильная инициализация (с нулями) объектов типаunsigned char
. Все остальное не гарантируется для правильной инициализации и может содержать так называемый ловушка представление, что вызывает неопределенное поведение. Другими словами, для любого типа, кромеunsigned char
вышеупомянутый все-нулевой бит паттерн может представлять собой незаконное значение, представление ловушку.позже, в одном из Технические исправления к стандарту C99, поведение было определено для всех целочисленных типов (что имеет смысл). Т. е. формально в текущем языке C вы можете инициализировать только целочисленные типы с помощью
calloc
(иmemset(..., 0, ...)
). Используя его для инициализации и все остальное в общем случае приводит к неопределенному поведению, с точки зрения языка Си.на практике
calloc
работает, как мы все знаем :), но хотите ли вы его использовать (учитывая вышеизложенное), зависит от вас. Лично я предпочитаю избегайте его полностью, используйтеmalloc
вместо этого и выполните мою собственную инициализацию.наконец, еще одна важная деталь заключается в том, что
calloc
требуется для расчета конечного размера блока внутри, путем умножения размера элемента на количество элементов. А делать, чтоcalloc
необходимо следить за возможным арифметическим переполнением. Это приведет к неудачному выделению (нулевой указатель), если запрошенный размер блока не может быть правильно вычислен. Между тем, вашmalloc
версия не делает никаких попыток следить за переполнением. Он выделит некоторый "непредсказуемый"объем памяти в случае переполнения.
из статьи бенчмаркинг весело с calloc () и нулевые страницы on блог Георга Хагера
при выделении памяти с помощью calloc (), объем запрашиваемой памяти не выделяется сразу. Вместо этого все страницы, принадлежащие блоку памяти, соединяются с одной страницей, содержащей все нули, с помощью некоторой магии MMU (ссылки ниже). Если такие страницы только читаются (что было верно для массивов b, c и d в исходной версии benchmark), данные предоставляются с одной нулевой страницы, которая – конечно же – помещается в кэш. Так много для ядер цикла с привязкой к памяти. Если страница записывается (независимо от того, как), возникает ошибка, "реальная" страница сопоставляется и нулевая страница копируется в память. Это называется copy-on-write, хорошо известный подход к оптимизации (который я даже преподавал несколько раз в своих лекциях на C++). После этого трюк с нулевым чтением больше не работает для этой страницы, и именно поэтому производительность была такой высокой понизьте после вставки-предположительно избыточного-цикла инициализации.
calloc
обычноmalloc+memset
до 0обычно немного лучше использовать
malloc+memset
явно, особенно, когда вы делаете что-то вроде:ptr=malloc(sizeof(Item)); memset(ptr, 0, sizeof(Item));
что лучше, потому что
sizeof(Item)
известно компилятору во время компиляции, и компилятор в большинстве случаев заменит его наилучшими инструкциями к нулевой памяти. С другой стороны, еслиmemset
происходитcalloc
, размер параметра распределения не компилируется вcalloc
код и реальныеmemset
часто вызывается, который обычно содержит код, чтобы сделать байт за байтом заполнить до длинной границы, чем цикл, чтобы заполнить память вsizeof(long)
куски и, наконец, байт за байтом заполняют оставшееся пространство. Даже если распределитель достаточно умен, чтобы вызвать некоторыеaligned_memset
это все равно будет общая петля.одно заметное исключение будет, когда вы делаете malloc / calloc очень большой кусок памяти (некоторые power_of_two килобайт) в этом случае выделение может быть сделано непосредственно из ядра. Поскольку ядра ОС обычно обнуляют всю память, которую они отдают по соображениям безопасности,достаточно умный calloc может просто вернуть ее с дополнительным обнулением. Опять же - если вы просто выделяете что-то, что вы знаете, мало, вам может быть лучше с производительностью malloc+memset.
malloc()
выделяет блок памяти заданного размера (в байтах) и возвращает указатель на начало блока.void *malloc(size_t size);
malloc()
не инициализирует выделенную память.
calloc()
выделяет память, а также инициализирует выделяет память для всех битов ноль.void *calloc(size_t num, size_t size);
Разница 1: malloc () обычно выделяет блок памяти и инициализирует сегмент памяти. calloc () выделяет блок памяти и инициализирует весь блок памяти до 0.
разница 2: Если вы рассматриваете синтаксис malloc (), он будет принимать только 1 аргумент. Рассмотрим следующий пример:
data_type ptr = (cast_type *) malloc( sizeof(data_type)*no_of_blocks);
пример: Если вы хотите выделить 10 блоков памяти для int типа,
int *ptr = (int *) malloc(sizeof(int) * 10 );
Если вы рассматриваете синтаксис calloc (), он будет принимать 2 аргумента. Рассмотрим следующий пример:
data_type ptr = (cast_type *)calloc (no_of_blocks, (sizeof (data_type)));
пример: если вы хотите выделить 10 блоков памяти для типа int и инициализировать все это до нуля,
int *ptr = (int *) calloc(10, (sizeof(int)));
сходство:
и malloc() и calloc () вернут void* по умолчанию, если они не являются приведенными типами .!
есть два отличия.
Во-первых, это количество аргументов.malloc()
принимает один аргумент (требуемая память в байтах), в то время какcalloc()
требуется два аргумента.
Во-вторых,malloc()
не инициализирует выделенную память, в то время какcalloc()
инициализирует выделенную память до нуля.
calloc()
выделяет область памяти, длина будет произведением ее параметров.calloc
заполняет память нулями и возвращает указатель на first байт. Если он не может найти достаточно места, он возвращаетNULL
указатель.синтаксис:
ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block);
то естьptr_var=(type *)calloc(n,s);
malloc()
выделяет один блок памяти требуемого размера и возвращает указатель на первый байт. Если ему не удается найти требуемый объем памяти, он возвращает нулевой указатель.синтаксис:
ptr_var=(cast_type *)malloc(Size_in_bytes);
Элементmalloc()
функция принимает один аргумент, который является количеством байтов для выделения, в то время какcalloc()
функция принимает два аргумента, один из которых-количество элементов, а другой-количество байтов, выделяемых для каждого из этих элементов. Кроме того,calloc()
инициализирует выделенную память нулями, в то время какmalloc()
нет.
The
calloc()
функция, которая объявлена в<stdlib.h>
заголовок предлагает несколько преимуществ по сравнению с
разница еще не упомянул: лимит в размере
void *malloc(size_t size)
можно выделить только доSIZE_MAX
.
void *calloc(size_t nmemb, size_t size);
можно выделить оSIZE_MAX*SIZE_MAX
.эта способность не часто используется во многих платформах с линейной адресации. Такие системы ограничивают
calloc()
Сnmemb * size <= SIZE_MAX
.рассмотрим тип 512 байт под названием
disk_sector
и код хочет использовать много секторов. Здесь код может использоваться только доSIZE_MAX/sizeof disk_sector
сектора.size_t count = SIZE_MAX/sizeof disk_sector; disk_sector *p = malloc(count * sizeof *p);
рассмотрим следующее, что позволяет еще большее распределение.
size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX) disk_sector *p = calloc(count, sizeof *p);
теперь, если такая система может обеспечить такое большое распределение, это другое дело. Большинство сегодня не будет. Тем не менее, это произошло в течение многих лет, когда
SIZE_MAX
было 65535. Учитывая закон Мура, подозреваю, что это будет происходить около 2030 года с некоторыми моделями памяти сSIZE_MAX == 4294967295
и пулы памяти в 100 Гбайт.
malloc (): выделяет запрошенный размер байтов и возвращает указатель первый байт выделенного пространства
calloc (): выделяет пространство для элементов массива, инициализирует до нуля, а затем возвращает указатель на память
malloc()
иcalloc()
являются функциями из стандартной библиотеки C, которые позволяют динамическое выделение памяти, что означает, что они оба позволяют выделение памяти во время выполнения.их прототипы выглядят следующим образом:
void *malloc( size_t n); void *calloc( size_t n, size_t t)
есть в основном два различия между ними:
поведение:
malloc()
выделяет блок памяти, не инициализируя его, и чтение содержимого из этого блока приведет к значениям мусора.calloc()
, с другой стороны, выделяет блок памяти и инициализирует его нулями, и, очевидно, прочитав содержимое этого блока приведет к нулям.синтаксис:
malloc()
принимает 1 аргумент (размер, который будет выделен), иcalloc()
принимает два аргумента (количество выделяемых блоков и размер каждого блока).возвращаемое значение как указатель на выделенный блок памяти, в случае успеха. В противном случае, NULL будет возвращается с указанием сбоя выделения памяти.
пример:
int *arr; // allocate memory for 10 integers with garbage values arr = (int *)malloc(10 * sizeof(int)); // allocate memory for 10 integers and sets all of them to 0 arr = (int *)calloc(10, sizeof(int));
та же функциональность, что и
calloc()
может быть достигнуто с помощьюmalloc()
иmemset()
:// allocate memory for 10 integers with garbage values arr= (int *)malloc(10 * sizeof(int)); // set all of them to 0 memset(arr, 0, 10 * sizeof(int));
отметим, что
malloc()
предпочтительно использовать болееcalloc()
так как это быстрее. Если требуется нулевая инициализация значений, используйте .
основные различия между malloc и calloc являются:
- malloc означает выделение памяти в то время как calloc означает непрерывные распределения.
Танос берет только один аргумент, размер блока в то время как calloc принимает два аргумента, количество выделяемых блоков и размер каждого блока.
ptr = (cast-type*) malloc (размер байта) // Мэллок
ptr = (cast-type*)calloc (нет блоков, размер блока); // calloc
malloc не выполняет инициализацию памяти и все адреса хранят мусора стоимостью в то время как calloc выполняет инициализацию памяти и адреса инициализируются либо нулевые или нулевые значения.
имя malloc и calloc () - это библиотечные функции, которые динамически выделяют память.
Это означает, что память выделяется во время выполнения(выполнение программы) из сегмента кучи.инициализации: malloc() выделяет блок памяти заданного размера (в байтах) и возвращает указатель на начало блока.
> malloc() doesn’t initialize the allocated memory. If we try to access the content of memory block then we’ll get garbage values. void * > malloc( size_t size ); > calloc() allocates the memory and also initializes the allocates memory block to zero. If we try to access the content of these blocks then we’ll get 0. > void * calloc( size_t num, size_t size );
ряд аргументов: в отличие от malloc (), calloc () принимает два аргумента: 1) количество выделяемых блоков. 2) Размер из каждого блока.
Самое Главное :
было бы лучше использовать malloc над calloc, если мы не хотим нулевой инициализации, потому что malloc быстрее, чем calloc. Так что если мы просто хочу скопировать некоторые вещи или сделать что-то, что не требует заполнение блоков нулями, тогда Мэллок будет лучше выбор.
malloc() принимает один аргумент, в то время как calloc () принимает два.
во-вторых, malloc() не инициализирует выделенную память, а calloc() инициализирует выделенную память до нуля. Оба malloc и calloc используются в языке C для динамического выделения памяти они получают блоки памяти динамически.
char *ptr = (char *) malloc (n * sizeof(char));
просто выделяет
n bytes
памяти без какой-либо инициализации (т. е. эти байты памяти будут содержать любые значения мусора).,char *ptr = (char *) malloc (n, sizeof(char));
calloc()
метод в c выполняет инициализацию как0
значение для всех занятых байтов памяти в дополнение к функции, котораяmalloc()
делает.но кроме этого, есть очень важное отличие. Во время вызова
malloc(x)
он выделит память (равную X блокам) и вернет указатель на первый выделенный байт. Однако, он не будет проверять, если точно х блоков памяти. Это приведет к переполнению памяти. Однакоcalloc()
проверяет размер выделения. Если он не справляется с выделением памяти или проверкой выделенных байтов, он просто возвращает null.