C语言 realloc()可能泄漏:当realloc()分配内存失败时,原始指针丢失



我知道这个问题已经被问过很多次了,但似乎每次这个问题的发生都略有不同。

我有以下C应用程序,它从一个名为word_generator()的函数接收字符串,然后过滤每个传入字符串,一旦满足条件,当前字符串存储在一个名为output_char_buffer的字符数组中。

由于传入数据的长度是可变的,因此过程中涉及的字符数组需要动态调整大小。

应用程序似乎正在工作,但是静态分析工具用以下消息抱怨:

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]: %sn", 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("tt__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: %sn", 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));

您应该将返回值存储到一个临时变量中,以便在失败的情况下释放原始指针,从而避免内存泄漏。

还要注意,代码中的清理是不完整的:您应该释放input_char_bufferoutput_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]: %sn", 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("tt__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: %sn", output_char_buffer);
// Clean-up and finish.
free(output_char_buffer);
output_char_buffer = NULL;
return 0;
}

相关内容

  • 没有找到相关文章

最新更新