В чем разница между GlobalAlloc и LocalAlloc... И чем лучше выделять память... Что такое HeapAlloc...
Для Win32 LocalAlloc == GlobalAlloc, у 9x даже адреса этих функций в экспорте kernel32.dll одинаковые.
Нужен большой блок памяти? - тогда VirtualAlloc. Нужно много маленьких блоков - тогда HeapAlloc. HeapAlloc хорош для открытия документов. Пример: открываем текстовый файл и делаем отдельный HeapCreate для этого документа. Каждую строку можно аллоцировать через HeapAlloc/HeapReAlloc. Когда файл закрываем - освобождаем весь Heap сразу (HeapDestroy), без освобождения каждой строки. Очень быстро и нет утечки памяти.
Вот интересный код: Код (Text): VOID FindHeapOverhead () { HANDLE h = HeapCreate (1, 4096, 0); PVOID p1 = HeapAlloc (h, 1, 32); PVOID p2 = HeapAlloc (h, 1, 32); UINT uiDistance = (PBYTE) p2 - (PBYTE) p1; CHAR str [64]; sprintf (str, "Distance = %d bytes", uiDistance); MessageBox (0, str, "Research", 0); HeapDestroy (h); }
никакой разницы между Virtual и Global почти нету. Virtualalloc это расширенный аналог Global. просто в Виртуал можно не выделять а резервировать память, а когда понадобится то и использовать, глобал же выделяет сразу "физическую"(на самом деле тоже виртуальную память).
Pushkoff Неправильная постановка вопроса: если выделить тысячу страниц, то уйдёт действительно 4 Мб. А если выделить 1000 раз по 32 байта, то 32 кБ. Т.е. можно выделить 32 кБ и побить этот кусок на 1000 частей. Совсем не обязательно под каждый кусок в 32 байта выделять страницу
LocalAlloc и GlobalAlloc - устаревшие, оставлены для совместимости с Win16, использовать не рекомендуется, за исключением случаев, когда в MSDN явно написано иное. На NT+ они сводятся к RtlAllocateHeap + проверки для поддержки флагов. HeapAlloc - напрямую RtlAllocateHeap. RtlAllocateHeap выделяет память округляя размер вверх до 8ми байт (на x86) + 8 байт на служебную информацию. Для блоков > 512Кб вызывает уже VirtualAlloc (NtAllocateVirtualMemory) + 32 байта на служебную информацию. VirtualAlloc коммитит память страницами по 4К, если резервирует - то по 64К. Всё это в MSDN есть, детали вроде 8ми байт в отладчике можно посмотреть... хм, а впрочем AsmGuru62 предложил более простой способ
Sector > "никакой разницы между Virtual и Global почти нету. Virtualalloc это расширенный аналог Global" Ошибаешься. Тема конечно избитая, да ладно - повторенье мать ученья Virtual это первичный системный аллокатор, поддерживающий страничную организацию памяти Windows. В винде физ.память выделяется страницами по 4К, поэтому на физ.уровне любой процесс вместе со всеми своими секциями, стеками, хипами и V-аллоками может занимать у системы только целое число страниц памяти (не считая системных ресурсов на всевозможные хэндлы, которые винда хранит в своих "недрах"). Из страничной организации следуют особенности Virtual: 1) память выделяется страницами по 4К, 2) реальное выделение физ.памяти происходит не при вызове Virtual, а лишь при первом чтении\записи в commited страницу. Поэтому выделять маленький блок памяти (например 32байта) с помощью Virtual это просто глупо - во-первых, расточительно, т.к. ради 32 байт будет выделена целая страница, во-вторых, медленно, т.к. при первом чтении\записи произойдет исключение PageFault, на обработку которого винда потратит немеряно времени, да еще после выделения страницы старательно заполнит все 4К нуликами. Поэтому для выделения маленьких блоков и придуманы вторичные аллокаторы - менеджеры кучи (виндовые Heap\Global\Local, борландовские GetMem и malloc и т.п.), которые выделяют себе память VirtualAlloc'ом, а затем раздают ее небольшими порциями, взимая символическую плату в виде 8-байтного заголовка на каждый блок. Для маленьких блоков выгода налицо - и экономия памяти, т.к. в одной странице можно разместить до сотни 8+32 байтных блочков, и экономия времени - страница инициализируется один раз и при выделении следующих кусочков из той же страницы PageFault'ов уже нет. Причем Heap создается и частично заполняется служебной инфой во время загрузки PE-файла, поэтому при передаче управления потоку в хипе уже есть инициализированная страница и поэтому запрос 32 байт через HeapAlloc с последующей записью займет в итоге в сотни-тысячи раз меньше времени, чем через Virtual.
какой размер у кучи которая выделяется процессу при загрузке, можно ли этот размер изменить при компиляции или во время выполнения??? можно ли эту кучу освободить, и на её место выделить другую адрес которой будет выдаваться по GetProcessHeap()??? В какой куче выделяют память функции GlobalAlloc и LocalAlloc??? Зачем нужны функции Lock и Unlock???
Pushkoff По умолчанию 1Мб. Это значение хранится в заголовке экзешника. Линкер MS поддерживает ключ /HEAP. Попробуйте ф-цию HeapReAlloc. Это уже было. См. MSDN.
Pushkoff Память под кучу выделяется VirtualAlloc'ом, поэтому в PE-заголовке экзешника хранятся две величины SizeOfHeapReserve - первоначальный резерв адресов (обычно 1Мб) и SizeOfHeapCommit - первоначальный размер выделенной памяти (обычно 4K). При компиляции эти величины изменить можно, но ИМХО особого смысла это не имеет, т.к. 1) резервирование адресов каши не просит (память не занимает), 2) главная куча является растущей (growable) - если понадобится, то менеджер автоматом зарезервирует дополнительный сегмент адресов, 3) реальное выделение физ.памяти осуществляется только при первом чтении\записи в commited страницу - что одну выделяй, что 10 - пока не запишешь че-нить винда и ухом не поведет занимать драгоценное ОЗУ, 4) в самой же куче хранится служебную инфа для управления кучей, поэтому как минимум 4 или 8К она первоначально все равно занимает. Во время выполнения менеджер кучи при запросах HeapAlloc\ReAlloc\Free сам решает, сколько выделить и сколько освободить памяти. Другими способами повлиять на размер кучи нельзя. Удалить главную кучу процесса тоже нельзя (см. описание HeapDestroy в MSDN) Global\Local эквивалентны HeapAlloc(GetProcessHeap..), т.е. выделяют память в главной куче процесса. На поддержку флага GMEM_MOVEABLE в той же куче дополнительно выделяется страница под таблицу хэндлов перемещаемой памяти. С учетом того, что этот флаг практически бесполезен, его использование не по делу лишь отъедает лишнюю память и время (на заметку ученикам Iczeliona Соответсвенно GlobalLock\Unlock преобразует хэндл блока MOVEABLE памяти в указатель на этот блок и наоборот (по вышеупомянутой табличке). HeapLock\Unlock блокирует кучу для предотвращения конфликтов одновременного доступа двух и более потоков