【问题标题】:binary file fread/fwrite and calloc/free memory leak?二进制文件 fread/fwrite 和 calloc/free 内存泄漏?
【发布时间】:2015-08-26 20:27:14
【问题描述】:

我正在尝试处理一些相当大的二进制文件(每个文件最多 20gb)。为此,我想分块读取它们,处理并写入新文件。

要读取文件,我使用:

fp = fopen(filename,"rb"); //open binary file to read
fseek(fp, start_of_chunk, SEEK_SET); //set cursor to current chunk
fread(data,size_of_chunk,1,fp); //read one chunk of data
fclose(fp);

然后我使用 calloc 分配一些数组并处理数据。 要写回去,我使用:

fout = fopen(file_out,"ab"); //open output binary file in append mode
fwrite(processed_data,size_of_processed_data,1,fout);
fclose(fout);

最后,我对每个分配的变量使用 free()(最大的是读取数据块(~400 MB),最小的是大约 1kB)并从读取下一个块重新开始。

输出工作正常,但进程不断消耗内存,就像没有明天一样。一个 800 MB 的测试文件会占用多达 6 GB 的 RAM,而且还在稳步上升。一次读取整个文件使用的内存量与读取块的内存量几乎相同。在循环之间使用 free() 甚至不会释放 5% 的已用内存,即使这些变量包含 99% 的数据。

由于我是 C 编程的新手,有什么我可能会遗漏的吗?我在另一个线程中读到操作系统(在我的情况下是 Windows 10 x64,在 Windows 7 x64 上存在同样的问题)可能太慢而无法释放内存。在我的情况下,阅读更大的块并没有帮助。所有文件句柄在读/写后关闭,所有分配的数组在最后被释放。

编辑:我在循环中多次分配。我正在使用

free(data);
data = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t));

在每次调用之前读取数据。为了处理块的某个部分,我正在使用

data_part = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t));
memmove(data_part,pointer_to_part_of_chunk, size_of_data_part);

编辑 2:感谢 cmets,我更改了一些内容。尽管如此,内存负载仍在稳步上升(比以前慢)。这是代码:

//initiate variables
//allocate arrays
data = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t));
array1 = (uint16_t*)calloc(number_of_elements1,sizeof(uint16_t));
array2 = (uint16_t*)calloc(number_of_elements2,sizeof(uint16_t)); //and so on

//some precalculations

//start of the loop
while (not_end_of_the_file){
    fp = fopen(filename,"rb"); //open binary file to read
    fseek(fp, start_of_chunk, SEEK_SET); //set cursor to current chunk
    fread(data,size_of_chunk,1,fp); //read one chunk of data
    fclose(fp);

    //calculate stuff
    start_of_chunk = start_of_chunk + increment;
    for (i=0;i<I;i++){
        memmove(array1,pointer_to_part_of_data, size_of_array1);
        if (statement){
            subfunction1(array1);
        }
        else{
            subfunction2(array1);
        }; //nothing more than some for loops, if statements and arithmetic operations
    //NO further allocations here, all buffers will be reused
    };

    //write result
    fout = fopen(file_out,"ab"); //open output binary file in append mode
    fwrite(processed_data,size_of_processed_data,1,fout);
    fclose(fout);
};

子函数中发生了一些分配,但是应该在子函数完成后释放内存,不是吗?

【问题讨论】:

  • 我们需要查看更多代码。听起来您可能会在循环中重复分配内存,而不是只分配一次并重用它。
  • 很确定您在未向我们展示的代码中做错了什么。请发帖MCVE
  • @Barmar 我确实在重复分配。我会尝试添加更多代码。
  • 编辑没有帮助。您是在要求我们通过显微镜检查大象。
  • “子函数中发生了一些分配,但是在子函数完成后应该释放内存,不是吗?”不,内存从malloc和朋友永远不会自动释放。如果你不free 它,它会一直保留在内存中,直到程序退出。我认为您已经习惯了具有垃圾收集功能的语言,例如 Java。 C 没有垃圾回收。

标签: c memory memory-management memory-leaks


【解决方案1】:
free(data);
data = (uint16_t*)calloc(number_of_elements,sizeof(uint16_t));

您确定空闲行中data 的值是上次调用calloc 返回的值吗?如果您拨打免费电话时是NULL,那就是无操作。

【讨论】:

  • 不,我不是。我不知道这可能与以前分配的值不同。不过,我现在确实删除了免费调用,并将所有分配转移到循环之外(参见最新编辑)。尽管如此,在计算过程中内存使用量不断增加,即使它应该只覆盖现有数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 2021-03-09
  • 1970-01-01
相关资源
最近更新 更多