0

这是一个简单的程序,它将文件“hello.txt”读入一个动态分配的缓冲区,最初大小为 10(当它被填满时大小翻倍)

运行 valgrind 时,似乎存在内存泄漏,但我不确定问题出在哪里。我在使用后释放了缓冲区的内存。

错误似乎是“条件跳转或移动取决于未初始化的值”

任何人都可以帮助确定是否存在内存泄漏?如果不是,那是什么问题?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 10

int main(int argc, char const *argv[])
{
    FILE *source;
    source = fopen("hello.txt","r");
    char *buffer = (char *)malloc(BUFFERSIZE);

    int current_size = BUFFERSIZE;
    int len = 0;
    char c;
    while((c = fgetc(source)) != EOF)
    {
        if(len == current_size-1)
        {
            current_size *= 2;
            buffer = (char *)realloc(buffer,current_size);
        }
        buffer[len] = c;
        len++;
    }                                                                
    printf("%s",buffer);
    free(buffer);

    return 0;
}
4

5 回答 5

3

错误似乎是“条件跳转或移动取决于未初始化的值”

那你为什么要问内存泄漏?此错误的来源很可能是对printf("%s", buffer)where的调用buffer不是有效字符串(无'\0'终止符)。

您的代码的另一个问题是您将返回值分配fgetc给 a char。您应该更改char cint c.

于 2013-01-24T19:08:42.357 回答
1

如果这是 valgrind 抱怨,它这样做是因为您将 realloc 的返回分配给您正在重新分配的缓冲区。由于 realloc 如果无法增大缓冲区将返回 NULL,这可能导致缓冲区的新值被分配给 NULL 并且旧值被泄露。

通常的比喻是这样的:

char * new_buffer = realloc(buffer, current_size);
if (!new_buffer) {
    handle_error();
}
buffer = new_buffer;

C 中的最佳实践也是不要从 malloc 或 realloc 中转换返回值。不值得一提的是这里;SO 有很多资源专门用来回答这个问题。

于 2013-01-24T19:01:58.033 回答
0

出于好奇,我在您的一段代码上尝试了 MemoryScape (TotalView),它没有显示任何内存泄漏(source并且buffer变量是引用的块,这意味着可以在程序的当前变量数据中的某处找到这些内存块的地址)。

我认为 Valgrind 肯定在这里显示误报(我不知道幕后的泄漏检测算法是什么)。

于 2013-02-01T10:35:45.867 回答
0

您在声明它们时缺少 NULL 检查并初始化指向 NULL 的指针。

使用 valgrind 选项--track-origins=yes让它跟踪未初始化值的来源。这会使其变慢,但会帮助您追踪未初始化值的来源。

希望此选项将帮助您在将来解决任何此类问题。

于 2013-01-24T19:01:35.557 回答
0

您需要使用临时指针:

char *temp = (char *)realloc(buffer,current_size);
if (!temp)
{
   fprintf(stderr, "Out of memory...\n");
   free(buffer);
   exit(1);
}
buffer = temp;

编辑我还注意到您正在转换 malloc 和 realloc - 这通常表明您正在使用 C++ 编译 C,这并不理想。如果您使用的是 IDE,您可能需要对其进行设置,以便它使用 C 而不是 C++ 来编译您的代码 - 通常可行的一种方法是将文件重命名为 myfile.c 而不是 myfile.cpp - 您可能必须删除它并将其重新添加到项目中以使更改生效。你可以通过转换 malloc/realloc 得到一些非常讨厌的错误。

编辑:您也没有为缓冲区中的字符串设置结束标记 - 您应该执行类似的操作

buffer[len] = '\0'; 

在你的while循环之后。请记住,如果文件也为空,您的 fgetc() 中可能会得到“无”,因此 len 可能为零。

你原来的 malloc 也应该检查 NULL。

于 2013-01-24T19:02:37.617 回答