动态数组:使用realloc()而不会出现内存泄漏
我使用realloc来调整分配的内存:
char **get_channel_name(void) { char **result; int n; result = (char **) 0; for (elem = snd_mixer_first_elem(handle), n = 0; elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; if (snd_mixer_selem_has_playback_volume(elem) && snd_mixer_selem_has_playback_switch(elem) && snd_mixer_selem_has_capture_switch(elem)) { if (result == (char **) 0) result = (char **) malloc(sizeof(char *)); else result = (char **) realloc(result, sizeof(char *) * (n + 1)); /* nulled but not freed upon failure */ result[n++] = strdup(snd_mixer_selem_get_name(elem)); } } if (result == (char **) 0) return NULL; result = (char **) realloc(result, sizeof(char *) * (n + 1)); /* nulled but not freed upon failure */ result[n] = NULL; return result; }
当我用cppcheck工具检查代码静态C / C ++代码分析时,打印出以下警告:
Common realloc mistake: 'result' nulled but not freed upon failure
如何修复这两个可能的内存泄漏?
如果realloc()
失败,则返回NULL
。
所以,如果你这样做(假设realloc()
会失败)
result = realloc(result, ...);
result
将被指定为NULL
,它指向的内容不是free()
ed,而free()
ed的地址将丢失。
解决这个问题:
void * tmp = realloc(result, ...); if (NULL == tmp) { /* Handle error case, propably freeing what result is pointing to. */ } else { result = tmp; }
修复“nulled但未释放失败”错误的技巧是将realloc
返回的值存储到单独的指针中,并在重新分配旧指针之前检查它是否为NULL
:
char **tmp = (char **) realloc(result, sizeof(char *) * (n + 1)); if (tmp) { result = tmp; } else { ... // Handle reallocation error }
现在结果的赋值受到NULL
检查的保护,你可以使用旧的值:你可以根据需要free
它,或者如果需要你可以继续使用它。 另一方面,原始代码不会为您提供相同的选项。
注意:当您将NULL
指针传递给realloc
,它的行为类似于malloc
。 这就是为什么你可以在第一次使用realloc
删除条件 – 替换它
if (result == (char **) 0) result = (char **) malloc(sizeof(char *)); else result = (char **) realloc(result, sizeof(char *) * (n + 1));
有了这个:
char** tmep = (char **) realloc(result, sizeof(char *) * (n + 1)); ... // check temp and assign result here
不要忘记将n
设置为零 – 目前,它是未初始化的,这是未定义的行为。