gpt4 book ai didi

c++ - 使用 fread() 以相反的顺序读取文件会导致内存泄漏?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:54:40 24 4
gpt4 key购买 nike

我有一个基本上是这样做的程序:

  1. 打开一些二进制文件
  2. 向后读取文件(向后,我的意思是它从 EOF 附近开始,并在文件开头结束读取,即“从右到左”读取文件),使用 4MB block
  3. 关闭文件

我的问题是:为什么内存消耗看起来像下面这样,即使我附加的代码中没有明显的内存泄漏?

Memory consumption during program execution

这是为获取上图而运行的程序源代码:

#include <stdio.h>
#include <string.h>

int main(void)
{
//allocate stuff
const int bufferSize = 4*1024*1024;
FILE *fileHandle = fopen("./input.txt", "rb");
if (!fileHandle)
{
fprintf(stderr, "No file for you\n");
return 1;
}
unsigned char *buffer = new unsigned char[bufferSize];
if (!buffer)
{
fprintf(stderr, "No buffer for you\n");
return 1;
}

//get file size. file can be BIG, hence the fseeko() and ftello()
//instead of fseek() and ftell().
fseeko(fileHandle, 0, SEEK_END);
off_t totalSize = ftello(fileHandle);
fseeko(fileHandle, 0, SEEK_SET);

//read the file... in reverse order. This is important.
for (off_t pos = totalSize - bufferSize, j = 0;
pos >= 0;
pos -= bufferSize, j ++)
{
if (j % 10 == 0)
{
fprintf(stderr,
"reading like crazy: %lld / %lld\n",
pos, totalSize);
}

/*
* below is the heart of the problem. see notes below
*/
//seek to desired position
fseeko(fileHandle, pos, SEEK_SET);
//read the chunk
fread(buffer, sizeof(unsigned char), bufferSize, fileHandle);
}

fclose(fileHandle);
delete []buffer;
}

我也有以下观察:

  1. 尽管 RAM 使用量增加了 1GB,但整个程序在整个执行过程中仅使用了 5MB。
  2. 注释掉对 fread() 的调用消除了内存泄漏。这很奇怪,因为我没有在它附近的任何地方分配任何东西,这可能会触发内存泄漏...
  3. 此外,正常读取文件而不是向后读取文件(= 注释掉对 fseeko() 的调用),也会消除内存泄漏。这是非常奇怪的部分

更多信息...

  1. 以下没有帮助:
    1. 检查 fread() 的结果 - 没有产生异常。
    2. 切换到正常的 32 位 fseekftell
    3. 做类似 setbuf(fileHandle, NULL) 的事情。
    4. 做类似setvbuf(fileHandle, NULL, _IONBF, *any integer*)的事情。
  2. 通过 cygwin 和 mingw 在 Windows 7 上用 g++ 4.5.3 编译;没有任何优化,只是 g++ test.cpp -o test。两者都存在这种行为。
  3. 测试中使用的文件有 4GB 长,全是零。
  4. 图表中间奇怪的停顿可以用某种与此问题无关的临时 I/O 挂起来解释。
  5. 最后,如果我将读取包装在无限循环中...内存使用量在第一次迭代后停止增加。

我认为这与某种内部缓存有关,直到它被整个文件填满。它是如何在幕后真正运作的?我怎样才能以便携的方式防止这种情况发生?

最佳答案

我认为,这更多是操作系统问题(甚至是操作系统资源使用报告问题),而不是您的程序问题。当然,它只使用 5 MB 内存:1 MB 用于自身(库、堆栈等),4 MB 用于缓冲区。每当您执行 fread() 时,操作系统似乎会将文件的一部分“绑定(bind)”到您的进程,并且似乎不会以相同的速度释放它。由于您机器上的内存使用率很低,这不是问题:操作系统只是让已经读取的数据“停留”的时间超过必要的时间,可能假设您的应用程序可能会很快再次读取它,然后它不会必须再次进行绑定(bind)。

如果内存压力较高,那么操作系统很可能会更快地解除内存绑定(bind),这样您的内存使用历史上的跳转就会更小。

关于c++ - 使用 fread() 以相反的顺序读取文件会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18171981/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com