释放calloc后为什么MEMSET叫什么名字?

问题描述 投票:4回答:3

我研究了一些图书馆的代码,发现来电calloc有后跟memsetcalloc分配的块。我发现与只是分配之前存储callocmalloc + memset并呼吁memset之间的差异比较全面的回答了这个问题:

Why malloc+memset is slower than 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

如果链接真正的Bug报告文本被感动:

glibc的:释放calloc()返回非zero'ed存储器

问题描述:

在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()的事情多的时候,这确实使事情变得不稳定。

请尽快以此为尽快修复,我甚至跑那么远,把它称为一个可能的安全问题。

c malloc calloc memset
3个回答
7
投票

调用memset()确保OS实际上做的虚拟内存映射。正如你链接的问题的答案指出,calloc()可以优化,使得实际的内存映射被推迟。

应用程序可能有理由不推迟虚拟存储器映射的实际创建 - 诸如使用缓冲液从一个非常高速的设备来读取,虽然在使用memset()零出的存储器的情况下,使用calloc()代替malloc()的似乎是多余的。


2
投票

没有人是完美的,仅此而已。是的,memset到零以下一个calloc是奢侈的。如果你想以保证您拥有您所要求的内存的明确memset,那么就应该遵循malloc代替。

新的代码具有每1000行约20 bug和概率法则意味着不是所有的人都淘汰掉。加上这是不是一个真正的错误,因为还有待观察无不良行为。


1
投票

我称之为一个错误,因为它是在做无谓的工作,指定calloc()为什么清除它再次回到已经清除内存呢?也许是失败的重构,当有人从malloc()切换。

如果代码是开源的和/或在你要访问的资源库,我会检查提交历史的线路,看看已经持续。随着一点点运气,有一个提交信息,告诉的动机......

© www.soinside.com 2019 - 2024. All rights reserved.