Используйте calloc
для нулевых значений, но только тогда, когда нулевое заполнение действительно необходимо.
Вы должны всегда использовать calloc(count,size)
вместо buff=malloc(total_size); memset(buff,0,total_size)
.
Звонок на нуль-memset
является ключом. Оба malloc
и calloc
переведены на вызовы ОС, которые делают множество оптимизаций, используют аппаратные трюки, когда это возможно, и т. Д. Но мало того, что ОС может делать с memset
.
С другой стороны, когда вам нужно заполнить выделенную память нулем? Единственное общее применение - для элементов произвольной длины с нулевым концом, таких как C-строки. Если это так, конечно, пойдите с calloc
.
Но если вы выделяете структуры, в которых элементы являются либо фиксированными, либо несут длину с ними произвольных размеров (например, строки и векторы C++), то заполнение нуля не является полезным вообще, и если вы пытаетесь полагаться на него, это может привести к сложным ошибкам.
Предположим, вы пишете свой собственный связанный список и решите пропустить нумерацию указателя на следующий узел, выделив память для узла с помощью calloc
. Он отлично работает, затем кто-то использует его с пользовательским размещением new, которое не заполняет нуль. Проблема в том, что иногда она будет заполнена нулем и может пройти все обычные испытания, выйти на производство, и там она будет разбиваться, иногда выходить из строя, ужасная неповторимая ошибка.
Для целей отладки нулевое заполнение обычно не так уж и хорошо. 0 слишком часто, вы редко можете написать что-то вроде assert(size);
, потому что это обычно действительное значение, вы тоже обрабатываете его с помощью if(!size)
, а не с утверждениями. На отладчике это тоже не попадет вам в глаза. В вашей памяти обычно есть нули. Лучшая практика заключается в том, чтобы избежать неподписанных типов для длин (подписанные длины могут быть полезны для обработки ошибок во время выполнения и некоторых из наиболее распространенных проверок переполнения). Таким образом, в то время как buff=malloc(total_size); memset(buff,0,total_size)
следует избегать, следующие в порядке:
const signed char UNINIT_MEM=MY_SENTINEL_VALUE;
buff=malloc(total_size);
#if DEBUG_MEMORY
memset(buff,UNINIT_MEM,total_size);
#endif
В режиме отладки, библиотеки времени выполнения или даже операционной системы сделать это для вас иногда, например, проверка this excellent post on VC++-specific sentinel values.
В C + почему вы хотите 'calloc()'? –
C или C++? В распределении памяти на языке C++, особенно, функции * alloc недоверчивы. – NathanOliver
Общее правило заключается в том, что если у вас есть проблема P, вы используете решение X, которое решает P, а не Y, что случается, чтобы решить P как побочный эффект. Там нет замены для критического мышления; программирование книгой рецептов редко работает. –