Roland M Smith Ответов: 2

Пожалуйста, помогите с проблемой heapalloc


Моя программа написана на обычном языке Си в Visual Studio 2017 и работает на Windows 10.

Он считывает двоичные файлы в память и извлекает информацию. Если я обрабатываю большое количество (более 100) действительно больших файлов (50-75 МБ), я получаю ошибку HeapAlloc. Я делаю HeapAlloc, обрабатываю файл, а затем делаю HeapFree. По какой-то причине куча продолжает увеличиваться в размере, пока не достигнет предела для 32-битных приложений.

У меня сложилось впечатление, что если я сделаю HeapFree, то следующий HeapAlloc будет повторно использовать память, уже используемую кучей. Похоже, что это не так.

Что я должен делать по-другому?

Что я уже пробовал:

// do this once at the start
hHeap = GetProcessHeap();

// the following once per file

hFile = CreateFile(lpszLibraryName,GENERIC_READ, FILE_SHARE_READ, NULL,						 
                    OPEN_EXISTING, 0, NULL);

dwFileSize = GetFileSize(hFile, &dwSizeHigh);

lpHeapData = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwFileSize + 1);

ReadFile(hFile, lpHeapData, dwFileSize, &dwBytesRead, NULL);

... process the file data ...

HeapFree(hHeap, 0, lpHeapData);

CloseHandle(hFile);

Richard MacCutchan

Есть ли какая-то вероятность того, что вы каким-то образом искажаете кучу при обработке данных файла? Кстати, почему вы просите HeapAlloc обнулить память, когда вы сразу же перезаписываете ее?

2 Ответов

Рейтинг:
5

steveb

Память, выделяемая HeapAlloc, не является подвижной. Поскольку память не является подвижной, куча может стать фрагментированной.
Вам нужно получить самый большой размер файла из 100 файлов и выделить память только один раз. Затем вы повторно используете его для всех 100 файлов и освобождаете его один раз


Rick York

Лучшая идея. Другая возможность состояла бы в том, чтобы сохранить текущий максимум и только освобождать/выделять, когда этот максимум превышен. Максимум может быть инициализирован с очень большим значением, чтобы минимизировать перераспределения.

Richard MacCutchan

Но именно для этого и существует функция HeapReAlloc.

steveb

Я думаю, что он делал вызов HeapAlloc и HeapFree 100 раз, что приведет к фрагментации кучи. На что я предположил, что ему не нужно выделять и освобождать память 100 раз. Вместо этого выделите память только один раз достаточно большой, чтобы вместить самый большой файл, а затем используйте эту же память для обработки всех 100 файлов. HeapAlloc печально известен своей фрагментацией

Richard MacCutchan

Я только что провел несколько тестов, выделяя и освобождая случайные буферы (от 5 Мб до 500 МБ), и это работает нормально.

Roland M Smith

Я выделяю достаточно места, чтобы вместить самый большой файл, обрабатываю все файлы, а затем освобождаю его один раз в конце. Это прекрасно работает!

Я обрабатывал около 160 файлов с диапазоном размеров от 50 КБ до 77 МБ.

Рейтинг:
1

Gerry Schmitz

Вы должны проверить результат от HeapFree() и LastError (), если хотите получить лучшее представление о том, что происходит.

Вы также "закрываете файл" (который обращается к куче) после освобождения кучи, когда вы больше не должны "касаться" кучи.

Функции HeapFree | Майкрософт документы[^]