Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Единственное заметное отличие состоит в том, что calloc
требуется для инициализации выделенного пространства нулями, в то время как в malloc
такой гарантии нет. В противном случае, я думаю, есть две разные функции только по историческим причинам.
Я услышал два [взаимоисключающих] объяснения, почему у него есть два аргумента:
calloc
берет на себя ответственность за проверку переполнения при умножении. Если общий размер запрашиваемого блока слишком велик (например, переполнения size_t
), calloc
возвращает нулевой указатель для указания сбоя. С malloc
вы должны следить за переполнением себя, что многие люди просто забывают сделать. (Хотя история стандартной библиотеки знает примеры реализаций calloc
, которые игнорировали переполнение и, следовательно, работали некорректно).
calloc
фактически позволяет выделить больше блоков памяти, чем диапазон типа size_t
, т. Е. calloc
может быть в состоянии выполнить надлежащее не переполнение большого умножения своих аргументов и выделить блок результирующего размера. По этой причине, поскольку calloc
использует два аргумента типа size_t
, он может выделить больше блоков, чем когда-либо сможет malloc
(поскольку malloc
принимает только один аргумент типа size_t
).
Я всегда считал, что первое объяснение правильное. Тем не менее, после прочтения некоторых постов здесь на SO у меня есть сомнения.
calloc(x,y)
эквивалентно malloc(x*y)
Но calloc
делает дополнительные (устанавливая значения на 0 с помощью) memset(block, 0, x*y)
Эта функция предназначена только для приятного прохождения размер элемента и количество элементов , когда в malloc необходимо умножить эти значения, чтобы получить необходимое количество байтов, эта функция также проверяет целочисленное переполнение при умножении.
Например, если вы хотите выделить память для 12 целых чисел и хотите сделать что-то с этими целыми числами, и вы, должно быть, установили ее значения на 0, используйте calloc(12, sizeof(int))
Но если вы хотите выделить некоторый блок памяти ( 256 байт), чтобы в будущем скопировать в него некоторую строку, тогда memset
для вас непригодна, тогда лучше использовать malloc(sizeof(char) * 256)
или, например, malloc(sizeof(wchar_t) * 256)
void *
calloc (size_t nmemb, size_t lsize)
{
void *ptr;
struct __meminfo *info;
size_t size = lsize * nmemb;
/* if size overflow occurs, then set errno to ENOMEM and return NULL */
if (nmemb && lsize != (size / nmemb))
{
set_errno (ENOMEM);
return NULL;
}
/* allocate memory */
ptr = malloc (size);
/* get pointer to info part of chunk */
info = __mem2info (ptr);
/* fill memory with zeros and set __MEM_CALLOC flag */
memset (ptr, 0, info->size);
info->flags |= __MEM_CALLOC;
return ptr; /* happy end */
}