How to zero out new memory after realloc

前端 未结 4 1084
闹比i
闹比i 2020-12-06 10:53

What is the best way to zero out new memory after calling realloc while keeping the initially allocated memory intact?

#include 
#include <         


        
相关标签:
4条回答
  • 2020-12-06 11:44

    There is no way to solve this as a general pattern. The reason why is that in order to know what part of the buffer is new you need to know how long the old buffer was. It's not possible to determine this in C and hence prevents a general solution.

    However you could write a wrapper like so

    void* realloc_zero(void* pBuffer, size_t oldSize, size_t newSize) {
      void* pNew = realloc(pBuffer, newSize);
      if ( newSize > oldSize && pNew ) {
        size_t diff = newSize - oldSize;
        void* pStart = ((char*)pNew) + oldSize;
        memset(pStart, 0, diff);
      }
      return pNew;
    }
    
    0 讨论(0)
  • 2020-12-06 11:46

    First of all, realloc can fail, so you need to check for NULL. Second, there is no better way to zero out the memory: just memset from the end of the old buffer to the end of the larger buffer.

    0 讨论(0)
  • 2020-12-06 11:52

    There is probably no need to do the memset: you may not be using colors[k] before setting it with something valid later. For example, your code sets colors[i] to a newly allocated color pointer, so you didn't need to set colors[i] to NULL.

    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 only portable thing you can do is to set each pointer to NULL in a loop:

    size_t k;
    for (k=COLORCOUNT; k < i+1; ++k) /* see below for why i+1 */
        colors[k] = NULL;
    

    Your primary problem is that your realloc() call is wrong. realloc() returns a pointer to the resized memory, it doesn't (necessarily) resize it in-place.

    So, you should do:

    /* i+1 because you later assign to colors[i] */
    rgb_t **tmp = realloc(colors, (i+1) * sizeof *tmp);
    if (tmp != NULL) {
        /* realloc succeeded, can't use colors anymore */
        colors = tmp;
    } else {
        /* realloc failed, colors is still valid */
    }
    

    If you really want to know what the memset() call should be, you need to set to zero the memory starting at colors+COLORCOUNT, and set i+1-COLORCOUNT members to zero:

    memset(colors+COLORCOUNT, 0, (i+1-COLORCOUNT) * sizeof *colors);
    

    But as I said above, all bytes zero is not guaranteed to be a NULL pointer, so your memset() is useless anyway. You have to use a loop if you want NULL pointers.

    0 讨论(0)
  • 2020-12-06 11:57

    Write your own function, say reallocz, that accepts the current size as a parameter, and calls realloc and memset for you. It really won't get much better than what you already have... it's C, after all.

    0 讨论(0)
提交回复
热议问题