Чтение файла с fread () в обратном порядке вызывает утечку памяти?

У меня есть программа, которая в основном делает это:

  1. Открывает какой-то бинарный файл
  2. Читает файл назад (в обратном направлении я имею в виду, что он начинается около EOF и заканчивается чтением в начале файла, то есть читает файл «справа налево»), используя фрагменты 4 МБ
  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. Несмотря на то, что использование ОЗУ увеличивается на 1 ГБ, вся программа использует всего 5 МБ для полного выполнения.
  2. Комментируя призыв к fread() из утечка памяти исчезает. Это странно, так как я не размещаю ничего рядом с ним, что может вызвать утечку памяти …
  3. Кроме того, чтение файла обычно, а не назад (= комментируя вызов fseeko() из), утечка памяти также устраняется. Это сверхъестественная часть.

Дальнейшая информация…

  1. Следующее не помогает:
    1. Проверка результатов fread() — ничего необычного не дает.
    2. Переключение на нормальное 32-битное fseek а также ftell,
    3. Делать такие вещи, как setbuf(fileHandle, NULL),
    4. Делать такие вещи, как setvbuf(fileHandle, NULL, _IONBF, *any integer*),
  2. Скомпилировано с g ++ 4.5.3 на Windows 7 через cygwin и mingw; без каких-либо оптимизаций, просто g++ test.cpp -o test, Оба представляют такое поведение.
  3. Файл, использованный в тестах, имел длину 4 ГБ и был заполнен нулями.
  4. Странная пауза в середине графика может быть объяснена каким-то временным зависанием ввода-вывода, не связанным с этим вопросом.
  5. Наконец, если я заверну чтение в бесконечный цикл … использование памяти перестает расти после первой итерации.

Я думаю, что это связано с каким-то внутренним созданием кэша, пока он не заполнится целым файлом. Как это действительно работает за кулисами? Как я могу предотвратить это портативным способом?

4

Решение

Я думаю, что это скорее проблема ОС (или даже проблема отчетности об использовании ресурсов ОС), чем проблема вашей программы. Конечно, он использует только 5 МБ памяти: 1 МБ для себя (библиотеки, стек и т. Д.) И 4 МБ для буфера. Всякий раз, когда вы выполняете fread (), ОС, кажется, «привязывает» часть файла к вашему процессу и, кажется, выпускает его не с той же скоростью. Поскольку использование памяти на вашем компьютере низкое, это не проблема: ОС просто сохраняет уже прочитанные данные «зависшими» дольше, чем необходимо, возможно, предполагая, что ваше приложение может прочитать их снова, в ближайшее время, а затем не Я должен сделать это снова.

Если бы нагрузка на память была выше, то операционная система, скорее всего, быстрее отсоединит память, так что скачок в истории использования памяти будет меньше.

2

Другие решения

У меня была точно такая же проблема, хотя в Java, но это не имеет значения в этом контексте. Я решил это, читая намного большие куски за раз. Я также читал фрагменты размером 4 Мб, но когда я увеличил их до 100-200 Мб, проблема ушла. Возможно, это сделает это и для вас. Я на Windows 7.

2

По вопросам рекламы [email protected]