将重新分配的内存设置为0是否常见?

时间:2015-09-23 06:27:28

标签: c memory idiomatic

在一本C书中,我在一个实例中找到了实现动态调整大小数组的代码(简化):

void *contents = realloc(array->contents, array->max * sizeof(void *));
array->contents = contents;

memset(array->contents + old_max, 0, array->expand_rate + 1);

来源:Learn C The Hard Way – Chapter 34

我对memset应该在这里实现的目标感到有些惊讶,但后来我才明白这是为了“#0;零”"重新分配的内存。

我用谷歌搜索,如果这是我在realloc之后应该做的事情,并找到了关于此的stackoverflow答案:

  

可能无需执行memset [...]

     

但是,即使你想把它归零所以一切都很好",或者真的需要新的指针NULL:C标准并不能保证所有-bits-zero是空指针常量(即NULL),所以memset()无论如何都不是正确的解决方案。

来源:How to zero out new memory after realloc

建议的解决方案而不是memset然后使用for循环来将内存设置为NULL

所以我的问题是,因为memset并不一定意味着将值设置为NULL并且for循环解决方案似乎有点单调乏味 - 是否真的需要设置新分配的内存?

3 个答案:

答案 0 :(得分:4)

  

所以我的问题是,因为memset并不一定意味着设置值   为NULL和for循环解决方案似乎有点乏味 - 是不是真的   需要设置新分配的内存吗?

realloc没有初始化新分配的内存段的值。

因此,如果您计划读取该(未初始化的)内存的值,则需要初始化内存。因为从未初始化的内存中读取值将触发未定义的行为。

顺便说一下,使用realloc(因为它可能失败)的安全方式是:

  // Since using realloc with size of 0 is tricky and useless probably
  // we use below check (from discussion with @chux)
  if (new_size == 0) 
    dosmth();
  else 
  {
    new_p = realloc(p, new_size);
    if (new_p == NULL)
    {
      // ...handle error
    }else
    {
      p = new_p;
    }
  }

答案 1 :(得分:0)

void *设置为0是一个等于NULL的值。可能memset(ptr, 0, size)可以 - 但需要查看更多代码以确定。

OTOH:代码是否正确?也许应该是

// memset(array->contents + old_max, 0, array->expand_rate + 1);
memset(array->contents + old_max, 0, sizeof(void *) * (array->expand_rate + 1) );

答案 2 :(得分:0)

这是错误的:

  

但是,即使你想“把它归零所以一切都很好”,或者   真的需要新的指针为NULL:C标准没有   保证all-bits-zero为空指针常量(即   NULL),所以memset()无论如何都不是正确的解决方案。

C标准确实确实保证了这一点。

根据C standard的第6.3.2.3节:

  

值为0的整型常量表达式,或此类表达式   强制转换为void *类型,称为空指针常量。如果为null   指针常量被转换为指针类型,由此产生   指针,称为空指针,保证比较不等于   指向任何对象或函数的指针。

     

将空指针转换为另一个指针类型会产生null   那种类型的指针。任何两个空指针都应该相等。

请注意,值为零的指针是 a 空指针。这并不意味着NULL本身必须为零。但另请注意,“任何两个空指针应比较相等”。所以任何空指针都等于NULL值。

由于memset()将第二个参数作为整数值,因此将零整数值传递给memset()将产生空指针。因为传递给memset()的值是“[a] n整数常量表达式,值为0”,按照6.3.2.3。