我有一个基本上这样做的程序:
我的问题是:为什么内存消耗看起来如下,即使我附加的代码中没有明显的内存泄漏?
以下是为获取上述图片而运行的程序源:
#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;
}
我还有以下观察:
fread()
的呼叫会导致内存泄漏消失。这很奇怪,因为我没有在它附近分配任何东西,这可能会引发内存泄漏...... fseeko()
),也会使内存泄漏消失。这是超奇怪的部分。更多信息......
fread()
的结果 - 不会产生任何异常。fseek
和ftell
。setbuf(fileHandle, NULL)
之类的内容。setvbuf(fileHandle, NULL, _IONBF, *any integer*)
之类的内容。g++ test.cpp -o test
。两者都表现出这种行为。我认为它与某种内部缓存构建有关,直到它填满整个文件。幕后真的如何运作?如何以便携方式防止这种情况?
答案 0 :(得分:2)
我认为,这是一个操作系统问题(甚至是操作系统资源使用报告问题),而不是程序问题。当然,它只使用5 MB内存:自身为1 MB(libs,堆栈等),缓冲区为4 MB。每当你执行fread()时,操作系统似乎将文件的一部分“绑定”到你的进程,并且似乎不会以相同的速度释放它。由于机器上的内存使用率很低,这不是问题:操作系统只是让已经读取的数据“闲置”超过必要的时间,可能假设您的应用程序可能很快再次读取它,然后它就不会必须再次进行绑定。
如果内存压力较高,那么操作系统很可能会更快地解除内存绑定,因此内存使用历史记录的跳跃会更小。
答案 1 :(得分:2)
我遇到了完全相同的问题,虽然在Java中但在这种情况下并不重要。我通过一次读取更大的块来解决它。我还读了4Mb大小的块,但是当我把它增加到100-200 Mb时,问题就消失了。也许它也适合你。我在Windows 7上。