Я исследовал код какой-то библиотеки и заметил, что после вызовов calloc
следует memset
для блока, выделенного calloc
.Я нашел этот вопрос с довольно полным ответом о различиях между calloc
и malloc
+ memset
и вызовом memset
непосредственно перед выделенным хранилищем:
Почему malloc + memset медленнеечем calloc?
То, что я до сих пор не могу понять, это то, почему кто-то хотел бы сделать это.Каковы преимущества этих операций?
Пример кода из упомянутой библиотеки:
light_pcapng_file_info *light_create_default_file_info()
{
light_pcapng_file_info *default_file_info = calloc(1, sizeof(light_pcapng_file_info));
memset(default_file_info, 0, sizeof(light_pcapng_file_info));
default_file_info->major_version = 1;
return default_file_info;
}
Код распределенной структуры (каждый массив содержит 32 элемента):
typedef struct _light_pcapng_file_info {
uint16_t major_version;
uint16_t minor_version;
char *file_comment;
size_t file_comment_size;
char *hardware_desc;
size_t hardware_desc_size;
char *os_desc;
size_t os_desc_size;
char *user_app_desc;
size_t user_app_desc_size;
size_t interface_block_count;
uint16_t link_types[MAX_SUPPORTED_INTERFACE_BLOCKS];
double timestamp_resolution[MAX_SUPPORTED_INTERFACE_BLOCKS];
} light_pcapng_file_info;
РЕДАКТИРОВАТЬ:
В дополнение к принятому ответу я хотел бы предоставить некоторую информацию, на которую мой коллега указал мне.В glibc была ошибка, которая иногда не позволяла calloc обнулять память.Вот ссылка: https://bugzilla.redhat.com/show_bug.cgi?id=1293976
Фактический текст сообщения об ошибке в случае перемещения ссылки:
glibc: calloc () возвращает ненулевую память
Описание проблемы:
В Facebook у нас было приложение, которое странно зависало и зависало при переходе от glibc-2.12-1.149.el6.x86_64 к glibc-2.12-1.163.el6.x86_64.Получается этот патч
glibc-rh1066724.patch
Введена проблема.
Вы добавили следующий бит в _int_malloc ()
/* There are no usable arenas. Fall back to sysmalloc to get a chunk from
mmap. */
if (__glibc_unlikely (av == NULL))
{
void *p = sYSMALLOc (nb, av);
if (p != NULL)
alloc_perturb (p, bytes);
return p;
}
Ноэто не нормально, alloc_perturb безусловно, передал байт memset в 0xf, в отличие от восходящего потока, где он проверяет, установлен ли perturb_byte.Это должно быть изменено на
if (p != NULL && && __builtin_expect(perturb_byte, 0))
alloc_perturb (p, bytes);
return p;
Патч, который я прикрепил, решает проблему для меня.
Эта проблема усугубляется тем фактом, что любой вид конфликта блокировки на результатах аренымы возвращаемся к mmap () и получаем новый фрагмент.Это потому, что мы проверяем, не повреждена ли неконтролируемая арена, которую мы проверяем, и делаем ли мы это циклично, и если мы переходим к началу, мы знаем, что ничего не нашли.За исключением случаев, когда наша начальная арена на самом деле не повреждена, мы по-прежнему возвращаем NULL, поэтому мы чаще прибегаем к этой функции mmap (), что действительно делает ее нестабильной.
Пожалуйста, исправьте это как можно скорееЯ бы даже зашел так далеко, что назвал это возможной проблемой безопасности.