too*_*zzy 4 c malloc memset calloc
我已经研究了一些库的代码,并注意到那里的调用calloc后面跟着memset分配的块calloc.我发现这个问题有一个非常全面的答案,关于calloc和malloc+ 之间的差异,并在分配存储之前memset调用memset:
我仍然无法理解的是为什么人们会这样做.这项业务有什么好处?
上面提到的代码示例库:
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;
}
Run Code Online (Sandbox Code Playgroud)
分配结构的代码(每个数组包含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;
Run Code Online (Sandbox Code Playgroud)
编辑:
除了接受的答案,我想提供一些我的同事指出的信息.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;
}
Run Code Online (Sandbox Code Playgroud)
但这不行,alloc_perturb无条件地将前端字节memset设置为0xf,与上游不同,它检查是否设置了perturb_byte.这需要改为
if (p != NULL && && __builtin_expect(perturb_byte, 0))
alloc_perturb (p, bytes);
return p;
Run Code Online (Sandbox Code Playgroud)
我附上的补丁修复了我的问题.
这个问题因为竞技场上的任何类型的锁争用导致我们回到mmap()的新块而加剧了这个问题.这是因为我们检查我们检查的无竞争竞技场是否已损坏,如果是我们循环,如果我们循环到开头,我们知道我们没有找到任何东西.除非我们的初始竞技场实际上没有损坏我们仍然会返回NULL,所以我们更经常地回到这个mmap()的东西,这真的让事情变得不稳定.
请尽快修复此问题,我甚至会将其称为可能的安全问题.
调用memset()可确保操作系统实际执行虚拟内存映射.正如您链接的问题的答案中所述,calloc()可以进行优化,以便延迟实际的内存映射.
应用程序可能有理由不推迟实际创建虚拟内存映射 - 例如使用缓冲区从非常高速的设备读取,尽管在使用memset()将内存清零的情况下,使用calloc()而不是malloc()看起来多余.