Global vs Local Alloc

Тема в разделе "WASM.WIN32", создана пользователем Pushkoff, 12 ноя 2005.

  1. Pushkoff

    Pushkoff New Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    40
    Адрес:
    Донецк
    В чем разница между GlobalAlloc и LocalAlloc...

    И чем лучше выделять память...

    Что такое HeapAlloc...
     
  2. __Dian

    __Dian New Member

    Публикаций:
    0
    Регистрация:
    15 окт 2005
    Сообщения:
    10
    Я обычно использую Local. Если юзать heap, то потом можно изменять размер выделенного блока
     
  3. Pushkoff

    Pushkoff New Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    40
    Адрес:
    Донецк
    какой минимальный размер блока выделяемый этими функциями... Что делает VirtualAlloc???
     
  4. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    Для Win32 LocalAlloc == GlobalAlloc, у 9x даже адреса этих функций в экспорте kernel32.dll одинаковые.
     
  5. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Нужен большой блок памяти? - тогда VirtualAlloc.

    Нужно много маленьких блоков - тогда HeapAlloc.



    HeapAlloc хорош для открытия документов. Пример: открываем текстовый файл и делаем отдельный HeapCreate для этого документа. Каждую строку можно аллоцировать через HeapAlloc/HeapReAlloc. Когда файл закрываем - освобождаем весь Heap сразу (HeapDestroy), без освобождения каждой строки. Очень быстро и нет утечки памяти.
     
  6. __Dian

    __Dian New Member

    Публикаций:
    0
    Регистрация:
    15 окт 2005
    Сообщения:
    10
    Минимальный размер по идее - 1 страница (4к)
     
  7. Pushkoff

    Pushkoff New Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    40
    Адрес:
    Донецк
    __Dian

    Это че если выделить 1000 обьектов по 32 байта то уйдет 4 мб а не 32 кб???
     
  8. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Вот интересный код:
    Код (Text):
    1.  
    2. VOID FindHeapOverhead ()
    3. {
    4.     HANDLE h = HeapCreate (1, 4096, 0);
    5.     PVOID p1 = HeapAlloc (h, 1, 32);
    6.     PVOID p2 = HeapAlloc (h, 1, 32);
    7.     UINT uiDistance = (PBYTE) p2 - (PBYTE) p1;
    8.     CHAR str [64];
    9.  
    10.     sprintf (str, "Distance = %d bytes", uiDistance);
    11.     MessageBox (0, str, "Research", 0);
    12.     HeapDestroy (h);
    13. }
    14.  
     
  9. Sector

    Sector New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2005
    Сообщения:
    49
    Адрес:
    Iceland
    никакой разницы между Virtual и Global почти нету. Virtualalloc это расширенный аналог Global. просто в Виртуал можно не выделять а резервировать память, а когда понадобится то и использовать, глобал же выделяет сразу "физическую"(на самом деле тоже виртуальную память).
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Pushkoff

    Неправильная постановка вопроса: если выделить тысячу страниц, то уйдёт действительно 4 Мб. А если выделить 1000 раз по 32 байта, то 32 кБ.

    Т.е. можно выделить 32 кБ и побить этот кусок на 1000 частей. Совсем не обязательно под каждый кусок в 32 байта выделять страницу
     
  11. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    LocalAlloc и GlobalAlloc - устаревшие, оставлены для совместимости с Win16, использовать не рекомендуется, за исключением случаев, когда в MSDN явно написано иное.



    На NT+ они сводятся к RtlAllocateHeap + проверки для поддержки флагов.



    HeapAlloc - напрямую RtlAllocateHeap.



    RtlAllocateHeap выделяет память округляя размер вверх до 8ми байт (на x86) + 8 байт на служебную информацию.

    Для блоков > 512Кб вызывает уже VirtualAlloc (NtAllocateVirtualMemory) + 32 байта на служебную информацию.



    VirtualAlloc коммитит память страницами по 4К, если резервирует - то по 64К.





    Всё это в MSDN есть, детали вроде 8ми байт в отладчике можно посмотреть...

    хм, а впрочем AsmGuru62 предложил более простой способ :derisive:
     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    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.
     
  13. Pushkoff

    Pushkoff New Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    40
    Адрес:
    Донецк
    какой размер у кучи которая выделяется процессу при загрузке, можно ли этот размер изменить при компиляции или во время выполнения???

    можно ли эту кучу освободить, и на её место выделить другую адрес которой будет выдаваться по GetProcessHeap()???

    В какой куче выделяют память функции GlobalAlloc и LocalAlloc???

    Зачем нужны функции Lock и Unlock???
     
  14. bers

    bers New Member

    Публикаций:
    0
    Регистрация:
    16 сен 2005
    Сообщения:
    139
    Адрес:
    Russia
    В PE-заголовке есть соответствующие поля...
     
  15. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Pushkoff



    По умолчанию 1Мб. Это значение хранится в заголовке экзешника.





    Линкер MS поддерживает ключ /HEAP.





    Попробуйте ф-цию HeapReAlloc.





    Это уже было.





    См. MSDN.
     
  16. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    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 блокирует кучу для предотвращения конфликтов одновременного доступа двух и более потоков