realloc() 可能泄漏:当 realloc() 分配内存失败时,原始指针丢失
realloc() possible leak: when realloc() fails in allocating memory, original pointer is lost
我知道这个问题已经被问过很多次了,但似乎每次出现这个问题都略有不同。
我有以下 C 应用程序,它从一个名为 word_generator()
的函数接收一个字符串,然后过滤每个传入的字符串,一旦满足条件,当前字符串将存储在一个名为 output_char_buffer
.
由于传入的数据是可变长度的,所以涉及到的char数组需要动态调整大小。
该应用程序似乎在运行,但静态分析工具正在抱怨并显示以下消息:
warning: V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 'output_char_buffer' is lost.
Consider assigning realloc() to a temporary pointer.
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *word_generator(int selector)
{
switch(selector)
{
case 0:
return "gpu-log-02_05_2022_12_37_56_784";
break;
case 1:
return "glsl-debug.txt";
break;
case 2:
return "compiler.log";
break;
case 3:
return "shader.pub";
break;
case 4:
return "fluid-sim-variantA.cache";
break;
default:
printf("ERROR: Request out of range!\n");
}
return "";
}
int main() {
char *output_char_buffer;
output_char_buffer = NULL;
// Simulate incoming data.
for (int i = 0; i < 5; i++)
{
printf("Test string[%d]: %s\n", i, word_generator(i));
unsigned long local_buffer_length = strlen(word_generator(i));
unsigned long input_buffer_length = 0;
char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
if (input_char_buffer != NULL)
{
strcpy(input_char_buffer, word_generator(i));
input_buffer_length = strlen(input_char_buffer);
}
else
{
// Clean-up.
free(input_char_buffer);
input_char_buffer = NULL;
printf("ERROR: Failed to allocate char buffer memory!\n");
// Exit with an error state.
return 1;
}
// Verbose debug.
printf("\tCurrent input buffer (value: %s, length: %lu)\n", input_char_buffer, input_buffer_length);
char key[] = "compiler.log";
// Verbose debug.
printf("\tCurrent key (value: %s, length: %lu)\n", key, strlen(key));
if (strcmp(input_char_buffer, key) == 0)
{
printf("\t\t__MATCH__\n");
output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
if (output_char_buffer != NULL)
{
strcpy(output_char_buffer, input_char_buffer);
}
else
{
// Clean-up.
free(output_char_buffer);
output_char_buffer = NULL;
printf("ERROR: Failed to fetch char buffer memory!\n");
// Exit with an error state.
return 1;
}
}
// Clean-up.
free(input_char_buffer);
input_char_buffer = NULL;
}
// Check the final value of the string container.
printf("Result: %s\n", output_char_buffer);
// Clean-up and finish.
free(output_char_buffer);
output_char_buffer = NULL;
return 0;
}
输出:
Test string[0]: gpu-log-02_05_2022_12_37_56_784
Current input buffer (value: gpu-log-02_05_2022_12_37_56_784, length: 31)
Current key (value: compiler.log, length: 12)
Test string[1]: glsl-debug.txt
Current input buffer (value: glsl-debug.txt, length: 14)
Current key (value: compiler.log, length: 12)
Test string[2]: compiler.log
Current input buffer (value: compiler.log, length: 12)
Current key (value: compiler.log, length: 12)
__MATCH__
Test string[3]: shader.pub
Current input buffer (value: shader.pub, length: 10)
Current key (value: compiler.log, length: 12)
Test string[4]: fluid-sim-variantA.cache
Current input buffer (value: fluid-sim-variantA.cache, length: 24)
Current key (value: compiler.log, length: 12)
Result: compiler.log
为该问题标记的行是这一行:
output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
处理这个问题的安全方法是什么?
代码中有 2 个 realloc
实例。第二个,原来的指针确实被覆盖了:
output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
您应该将 return 值存储到一个临时变量中,这样您就可以在发生故障时释放原始指针,从而避免内存泄漏。
另请注意,您的代码中的清理不完整:您应该释放 input_char_buffer
和 output_char_buffer
,以防它已在上一次迭代期间分配。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *word_generator(int selector) {
switch (selector) {
case 0: return "gpu-log-02_05_2022_12_37_56_784";
case 1: return "glsl-debug.txt";
case 2: return "compiler.log";
case 3: return "shader.pub";
case 4: return "fluid-sim-variantA.cache";
default: printf("ERROR: Request out of range!\n");
return "";
}
}
int main() {
char *output_char_buffer = NULL;
// Simulate incoming data.
for (int i = 0; i < 5; i++) {
const char *word = word_generator(i);
printf("Test string[%d]: %s\n", i, word);
size_t local_buffer_length = strlen(word);
char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
if (input_char_buffer == NULL) {
// Clean-up.
free(output_char_buffer);
output_char_buffer = NULL;
printf("ERROR: Failed to allocate char buffer memory!\n");
// Exit with an error state.
return 1;
}
strcpy(input_char_buffer, word);
size_t input_buffer_length = strlen(input_char_buffer);
// Verbose debug.
printf("\tCurrent input buffer (value: %s, length: %zu)\n",
input_char_buffer, input_buffer_length);
char key[] = "compiler.log";
// Verbose debug.
printf("\tCurrent key (value: %s, length: %zu)\n", key, strlen(key));
if (strcmp(input_char_buffer, key) == 0) {
printf("\t\t__MATCH__\n");
char *temp = (char *)realloc(output_char_buffer, local_buffer_length + 1);
if (temp == NULL) {
// Clean-up.
free(output_char_buffer);
output_char_buffer = NULL;
free(input_char_buffer);
input_char_buffer = NULL;
printf("ERROR: Failed to fetch char buffer memory!\n");
// Exit with an error state.
return 1;
}
output_char_buffer = temp;
strcpy(output_char_buffer, input_char_buffer);
}
// Clean-up.
free(input_char_buffer);
input_char_buffer = NULL;
}
// Check the final value of the string container.
printf("Result: %s\n", output_char_buffer);
// Clean-up and finish.
free(output_char_buffer);
output_char_buffer = NULL;
return 0;
}
我知道这个问题已经被问过很多次了,但似乎每次出现这个问题都略有不同。
我有以下 C 应用程序,它从一个名为 word_generator()
的函数接收一个字符串,然后过滤每个传入的字符串,一旦满足条件,当前字符串将存储在一个名为 output_char_buffer
.
由于传入的数据是可变长度的,所以涉及到的char数组需要动态调整大小。
该应用程序似乎在运行,但静态分析工具正在抱怨并显示以下消息:
warning: V701 realloc() possible leak: when realloc() fails in allocating memory, original pointer 'output_char_buffer' is lost.
Consider assigning realloc() to a temporary pointer.
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *word_generator(int selector)
{
switch(selector)
{
case 0:
return "gpu-log-02_05_2022_12_37_56_784";
break;
case 1:
return "glsl-debug.txt";
break;
case 2:
return "compiler.log";
break;
case 3:
return "shader.pub";
break;
case 4:
return "fluid-sim-variantA.cache";
break;
default:
printf("ERROR: Request out of range!\n");
}
return "";
}
int main() {
char *output_char_buffer;
output_char_buffer = NULL;
// Simulate incoming data.
for (int i = 0; i < 5; i++)
{
printf("Test string[%d]: %s\n", i, word_generator(i));
unsigned long local_buffer_length = strlen(word_generator(i));
unsigned long input_buffer_length = 0;
char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
if (input_char_buffer != NULL)
{
strcpy(input_char_buffer, word_generator(i));
input_buffer_length = strlen(input_char_buffer);
}
else
{
// Clean-up.
free(input_char_buffer);
input_char_buffer = NULL;
printf("ERROR: Failed to allocate char buffer memory!\n");
// Exit with an error state.
return 1;
}
// Verbose debug.
printf("\tCurrent input buffer (value: %s, length: %lu)\n", input_char_buffer, input_buffer_length);
char key[] = "compiler.log";
// Verbose debug.
printf("\tCurrent key (value: %s, length: %lu)\n", key, strlen(key));
if (strcmp(input_char_buffer, key) == 0)
{
printf("\t\t__MATCH__\n");
output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
if (output_char_buffer != NULL)
{
strcpy(output_char_buffer, input_char_buffer);
}
else
{
// Clean-up.
free(output_char_buffer);
output_char_buffer = NULL;
printf("ERROR: Failed to fetch char buffer memory!\n");
// Exit with an error state.
return 1;
}
}
// Clean-up.
free(input_char_buffer);
input_char_buffer = NULL;
}
// Check the final value of the string container.
printf("Result: %s\n", output_char_buffer);
// Clean-up and finish.
free(output_char_buffer);
output_char_buffer = NULL;
return 0;
}
输出:
Test string[0]: gpu-log-02_05_2022_12_37_56_784
Current input buffer (value: gpu-log-02_05_2022_12_37_56_784, length: 31)
Current key (value: compiler.log, length: 12)
Test string[1]: glsl-debug.txt
Current input buffer (value: glsl-debug.txt, length: 14)
Current key (value: compiler.log, length: 12)
Test string[2]: compiler.log
Current input buffer (value: compiler.log, length: 12)
Current key (value: compiler.log, length: 12)
__MATCH__
Test string[3]: shader.pub
Current input buffer (value: shader.pub, length: 10)
Current key (value: compiler.log, length: 12)
Test string[4]: fluid-sim-variantA.cache
Current input buffer (value: fluid-sim-variantA.cache, length: 24)
Current key (value: compiler.log, length: 12)
Result: compiler.log
为该问题标记的行是这一行:
output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
处理这个问题的安全方法是什么?
代码中有 2 个 realloc
实例。第二个,原来的指针确实被覆盖了:
output_char_buffer = (char*)realloc(output_char_buffer, (local_buffer_length + 1));
您应该将 return 值存储到一个临时变量中,这样您就可以在发生故障时释放原始指针,从而避免内存泄漏。
另请注意,您的代码中的清理不完整:您应该释放 input_char_buffer
和 output_char_buffer
,以防它已在上一次迭代期间分配。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *word_generator(int selector) {
switch (selector) {
case 0: return "gpu-log-02_05_2022_12_37_56_784";
case 1: return "glsl-debug.txt";
case 2: return "compiler.log";
case 3: return "shader.pub";
case 4: return "fluid-sim-variantA.cache";
default: printf("ERROR: Request out of range!\n");
return "";
}
}
int main() {
char *output_char_buffer = NULL;
// Simulate incoming data.
for (int i = 0; i < 5; i++) {
const char *word = word_generator(i);
printf("Test string[%d]: %s\n", i, word);
size_t local_buffer_length = strlen(word);
char *input_char_buffer = (char*)malloc(local_buffer_length + 1);
if (input_char_buffer == NULL) {
// Clean-up.
free(output_char_buffer);
output_char_buffer = NULL;
printf("ERROR: Failed to allocate char buffer memory!\n");
// Exit with an error state.
return 1;
}
strcpy(input_char_buffer, word);
size_t input_buffer_length = strlen(input_char_buffer);
// Verbose debug.
printf("\tCurrent input buffer (value: %s, length: %zu)\n",
input_char_buffer, input_buffer_length);
char key[] = "compiler.log";
// Verbose debug.
printf("\tCurrent key (value: %s, length: %zu)\n", key, strlen(key));
if (strcmp(input_char_buffer, key) == 0) {
printf("\t\t__MATCH__\n");
char *temp = (char *)realloc(output_char_buffer, local_buffer_length + 1);
if (temp == NULL) {
// Clean-up.
free(output_char_buffer);
output_char_buffer = NULL;
free(input_char_buffer);
input_char_buffer = NULL;
printf("ERROR: Failed to fetch char buffer memory!\n");
// Exit with an error state.
return 1;
}
output_char_buffer = temp;
strcpy(output_char_buffer, input_char_buffer);
}
// Clean-up.
free(input_char_buffer);
input_char_buffer = NULL;
}
// Check the final value of the string container.
printf("Result: %s\n", output_char_buffer);
// Clean-up and finish.
free(output_char_buffer);
output_char_buffer = NULL;
return 0;
}