我有一个程序,基本上是这样做的:
请看上面图片了解程序执行期间的内存消耗情况。
以下是运行以上程序的源代码:
我还有以下观察结果:
- 打开一些二进制文件
- 倒序读取文件(倒序指从EOF开始,以文件开头结束,即从右到左读取文件),使用4MB的块
- 关闭文件
请看上面图片了解程序执行期间的内存消耗情况。
以下是运行以上程序的源代码:
#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;
}
我还有以下观察结果:
- 尽管RAM使用量增加了1GB,但整个程序在整个执行过程中只使用了5MB。
- 注释调用
fread()
会消除内存泄漏。这很奇怪,因为我没有分配与之相近的任何东西,可能会触发内存泄漏... - 而且,正常读取文件而不是倒序读取(=注释掉
fseeko()
的调用),也会消除内存泄漏。这是极其奇怪的部分。
更多信息...
- 以下操作无效:
- 检查
fread()
的结果-没有异常情况。 - 切换到普通的32位
fseek
和ftell
。 - 执行
setbuf(fileHandle, NULL)
等操作。 - 执行
setvbuf(fileHandle, NULL, _IONBF, *任何整数*)
等操作。
- 检查
- 使用cygwin和mingw在Windows 7上通过g++ 4.5.3编译,没有进行任何优化,只是
g++ test.cpp -o test
。两者都表现出这种行为。 - 测试中使用的文件长度为4GB,全是零。
- 图表中间的奇怪暂停可能是由于某种与此问题无关的临时I/O挂起引起的。
- 最后,如果我将读取包装在无限循环中...内存使用量在第一次迭代后停止增加。
我认为这与某种内部缓存有关,直到它被整个文件填满。它在幕后真正工作的方式是什么?如何以可移植的方式防止它?
const int bufferSize = 4*1024*1024
不好... 应该是const int bufferSize = sizeof( int )*1024*1024
。 - Jacob Pollack