如何在realloc之后将新内存清零

Nic*_*unt 8 c null memory-management

在保持最初分配的内存完好无损的同时调用realloc后,将新内存清零的最佳方法是什么?

#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>

size_t COLORCOUNT = 4;

typedef struct rgb_t {
    int r;
    int g;
    int b;
} rgb_t;

rgb_t** colors;

void addColor(size_t i, int r, int g, int b) {
    rgb_t* color;
    if (i >= COLORCOUNT) {
        // new memory wont be NULL
        colors = realloc(colors, sizeof(rgb_t*) * i);
       //something messy like this...
        //memset(colors[COLORCOUNT-1],0 ,sizeof(rgb_t*) * (i - COLORCOUNT - 1));

         // ...or just do this (EDIT)
        for (j=COLORCOUNT; j<i; j++) {
            colors[j] = NULL;
        }

        COLORCOUNT = i;
    }

    color = malloc(sizeof(rgb_t));
    color->r = r;
    color->g = g;
    color->b = b;

    colors[i] = color;
}

void freeColors() {
    size_t i;
    for (i=0; i<COLORCOUNT; i++) {
        printf("%x\n", colors[i]);
        // can't do this if memory isn't NULL
       // if (colors[i])
         //   free(colors[i]);

    }
}


int main() {
    colors = malloc(sizeof(rgb_t*) * COLORCOUNT);
    memset(colors,0,sizeof(rgb_t*) * COLORCOUNT);
    addColor(0, 255, 0, 0);
    addColor(3, 255, 255, 0);
    addColor(7, 0, 255, 0);


    freeColors();
    getchar();
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*Par 8

作为一般模式,没有办法解决这个问题.原因是为了知道缓冲区的哪个部分是新的,你需要知道旧缓冲区有多长.在C中无法确定这一点,因此阻止了一般解决方案.

但是你可以像这样写一个包装器

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;
}
Run Code Online (Sandbox Code Playgroud)


Alo*_*hal 5

可能不需要执行以下操作:在使用稍后有效的内容设置它之前,memset您可能不会使用它。colors[k]例如,您的代码设置colors[i]为新分配的color指针,因此您不需要设置colors[i]NULL

但是,即使您想“将其清零,以便一切都很好”,或者确实需要新指针NULL:C 标准不保证所有位为零是空指针常量(即NULL),所以memset()无论如何都不是正确的解决方案。

您可以做的唯一可移植的事情是将每个指针设置为NULL循环:

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

您的主要问题是您的realloc()呼叫错误。 realloc()返回指向已调整大小的内存的指针,它不会(必然)就地调整其大小。

所以,你应该这样做:

/* 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 */
}
Run Code Online (Sandbox Code Playgroud)

如果您确实想知道调用memset()应该是什么,则需要将从 开始的内存设置为零colors+COLORCOUNT,并将i+1-COLORCOUNT成员设置为零:

memset(colors+COLORCOUNT, 0, (i+1-COLORCOUNT) * sizeof *colors);
Run Code Online (Sandbox Code Playgroud)

但正如我上面所说,所有字节为零并不能保证都是指针NULL,所以你的memset()无论如何都是无用的。如果你想要指针,你必须使用循环NULL