读入缓冲区时内存泄漏

时间:2013-01-24 18:57:50

标签: c memory valgrind memory-leaks

这是一个简单的程序,它将文件“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;
}

5 个答案:

答案 0 :(得分:3)

  

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

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

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

答案 1 :(得分: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有很多资源专门回答这个问题。

答案 2 :(得分:0)

在声明它们时,您缺少NULL检查并将指针初始化为NULL。

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

希望此选项可以帮助您解决任何此类问题。

答案 3 :(得分: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。

答案 4 :(得分:0)

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

我认为Valgrind肯定会在这里显示误报(我不知道场景后面有什么泄漏检测算法)。