繁体   English   中英

以相反顺序读取fread()文件会导致内存泄漏?

[英]Reading file with fread() in reverse order causes memory leak?

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

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

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

程序执行期间的内存消耗

以下是为获取上述图像而运行的程序源:

#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*)东西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(libs,堆栈等),缓冲区为4 MB。 每当你执行fread()时,操作系统似乎将文件的一部分“绑定”到你的进程,并且似乎不会以相同的速度释放它。 由于机器上的内存使用率很低,这不是问题:操作系统只是让已经读取的数据“闲置”超过必要的时间,可能假设您的应用程序可能很快再次读取它,然后它就不会必须再次做那个绑定。

如果内存压力较高,则操作系统很可能会更快地解除内存绑定,因此内存使用历史记录的跳跃会更小。

我有完全相同的问题,虽然在Java中,但在这种情况下无关紧要。 我通过一次读取更大的块来解决它。 我还读了4Mb大小的块,但是当我把它增加到100-200 Mb时,问题就消失了。 也许它也会为你做到这一点。 我在Windows 7上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM