Is it common practice to memset reallocated memory to 0?

佐手、 提交于 2019-12-12 17:23:33

问题


In a C book I found in an example for implementing a dynamically resizing array this code (simplified):

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

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

Source: Learn C The Hard Way – Chapter 34

I was a bit surprised what memset is supposed to achieve here, but then I understood it's used in order to "zero out" the reallocated memory.

I googled in order to find out, if this is what I'm supposed to do after a realloc and found a stackoverflow answer regarding this:

There is probably no need to do the memset […]

But, even if you wanted to "zero it out so everything is nice", or really need the new pointers to be NULL: the C standard doesn't guarantee that all-bits-zero is the null pointer constant (i.e., NULL), so memset() isn't the right solution anyway.

Source: How to zero out new memory after realloc

The suggested solution instead of memset is then to use a for loop in order to set the memory to NULL.

So my question is, as memset does not necessarily mean setting values to NULL and the for loop solution seems a bit tedious – is it really needed to set the newly allocated memory?


回答1:


So my question is, as memset does not necessarily mean setting values to NULL and the for loop solution seems a bit tedious – is it really needed to set the newly allocated memory?

realloc doesn't initialize values of the newly allocated memory segment.

So it is needed to initialize the memory if you are planning to read values of that (uninitialized) memory. Because reading values from that uninitialized memory will trigger undefined behaviour.

By the way, safe way to use realloc (since it can fail) is:

  // 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;
    }
  }



回答2:


Setting a void * to 0 is a value that will compare equal to NULL. Likely memset(ptr, 0, size) is OK - but need to see more code for certainty.

OTOH: is the code correct? Maybe should be

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



回答3:


This is wrong:

But, even if you wanted to "zero it out so everything is nice", or really need the new pointers to be NULL: the C standard doesn't guarantee that all-bits-zero is the null pointer constant (i.e., NULL), so memset() isn't the right solution anyway.

The C standard does in fact guarantee exactly that.

Per section 6.3.2.3 of the C standard:

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.

Note that a pointer with a value of zero is a null pointer. That doesn't mean NULL itself has to be zero. But also note that "any two null pointers shall compare equal". So any null pointer is equal to the NULL value.

Since memset() takes as its second argument an integer value, passing a zero integer value to memset() will produce null pointers. Because the value passed to memset() is "[a]n integer constant expression with the value 0", per 6.3.2.3.



来源:https://stackoverflow.com/questions/32732449/is-it-common-practice-to-memset-reallocated-memory-to-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!