Привет всем, я хотел спросить бы две вещи какой способ выделение памяти в винде лучше, GlobalAlloc, VirtualAlloc и т.п. ? И почему у меня не выделяется HGLOBAL в проге, просто давно не содился за ассемблер и может я, что делаю не так? syntax = fasm: Заранее благодарю...
Все элементарно ватсон. У тебя указано GMEM_ZEROINIT, а это получается GMEM_ZEROINIT+GMEM_FIXED (GMEM_FIXED=0) а оно возвращает сразу же указатель (сразу же после GlobalAlloc). Для создания кучи оставь Global. Тебе же не надо управляться с виртуальным пространством. тем более что тебе тут вообще без разници где память лежит.
Никогда не понимал зачем нужно усложнять. Вся память общая, любой поток к ней доступ имеет. Эффективнее и проще вызвать сервис NtAllocateVirtualMemory, либо если нужно из хипа память, то функций управления им множество.
Nt - я конечно в этом плохо разбираюсь, но функции с таким прификсом вроде вызываються с приложений работающих в ring0 или я не прав?, а мне надо сделать тупую прогу которая могла бы записовать и читать в файл древовидную структуру данных...
Вот простой макрос (FASM). По аналогии можно сделать и для free(), realloc(): Код (Text): macro malloc nBytes { invoke GetProcessHeap invoke HeapAlloc, eax, HEAP_NO_SERIALIZE, nBytes }
По поводу способа выделения памяти мс написали вот как: Другими словами, работа с памятью, используя эти функции, уже стала историей как и Windows 1.01 Лучше юзать связки HeapCreate - HeapDestroy, + HeapAlloc, HeapReAlloc, HeapSize, HeapFree и даже HeapValidate есть.
Вот еще простой способ: Код (Text): AllocateHeap proc near arg_0 = dword ptr 4 assume fs:nothing mov eax,fs:18h push [esp+arg_0] mov eax,[eax+30h] push 0 push dword ptr [eax+18h] call RtlAllocateHeap retn 4 AllocateHeap endp FreeHeap proc near arg_0 = dword ptr 4 assume fs:nothing mov eax,fs:18h push [esp+arg_0] mov eax,[eax+30h] push 0 push dword ptr [eax+18h] call RtlFreeHeap retn 4 FreeHeap endp push 1024 call AllocateHeap mov hMemory,eax ;---- push hMemory call FreeHeap
М-да, а я то функции правильно писал, я их не правильно вызывал... Ну, это я так пример привел, кому интересно... До: Код (Text): stdcall MemoryInit, [name#.table], [name#.LenTable] mov [name#.table+4], eax После: Код (Text): stdcall MemoryInit, name#.table, [name#.LenTable] mov [name#.table+4], eax Странно давно не кодил уже наверно больше полгода, даже какое то чувство появилось, что мир изменился... И ответный вопрос в придачу для программистов средней руки (не буду беспокоить мастеров), а смогу ли я создать без эксептионс 2000 куч с помощью HeapCreate? Просто помнится, что default process heap 1 мб, а если больше кучу делать все получиться?
Nt* это хэндлер в ядре для соотв. Zw*. В юзермоде Nt* просто мост на Zw*, Zw* и юзаем. Забудь про хип. Юзай это либо секции.
Глобал рушиться при увеличении размера блока, буду пробовать Хеап, в противном случае NtAllocateVirtualMemory... Завтра скажу результаты... А какие функции выделения памяти выделяют, точно запрошенному размеру, ну типа без выравнивания на 64? PS/ еп*аный FASM...
dgs Пора бы всё таки запомнить (тема тут тыщу раз поднималась), что Global/LocalAlloc и флаги GMEM_MOVEABLE/GMEM_FIXED это наследие win16 с её общим на все программы адресным пространством и сохранилось только для совместимости доисторическим наследием. Современные win не делят память на Global/Local и никакие блоки по своей иннициативе не перемещают, даже если они GMEM_MOVEABLE, ибо при раздельном адресном пространстве процессов это уже не актуально. Вместо них теперь HeapAlloс, которая для каши из мелких блоков. Если же нужен большой блок памяти или есть желание самому управлять своей кашей из блоков, тогда VirtualAlloc. Создавать свою дополнительную Heap нужно только если это действительно нужно (что вообще-то оооочень редко) в подавляющем большинстве программ правильно использовать GetProcessHeap, особенно бегиннерсам. Во всякие Zw* Nt*, rtl* не лезь пока они действительно не понадобятся. Если нужна надёжная (в смысле предсказуемая) работа с мелкими блоками, выделяй большой блок через VirtualAlloc и дели его сам как тебе надо, Heap это для каши из блоков, для которых не принципиально где и как они расположены, на то она и куча
"Они образованность свою показать хочут, вот и говорят о непонятном" (с) На каждый чих виртуальную память будем выделять, да? С гранулярностью в 4К (размер страницы, если точнее), да? Дерево из десяти тысяч объектов, каждый из которых размером 8 байт, при таком раскладе займет 400М, нормально, да?
Ursus О чём ты, ничего показать не хочу, загляни внутрь функций управления хипами, тогда увидишь что реально понять сложно. Никогда не видел отладочный останов изза "Heap corrupt detected", или необработанное исключение при перечислении куч ? Хип слишком сложный и как следствие не стабильный механизм. Нужно на первый чих выделить память а часть зарезервировать. Так делол бы я, впрочем мне всёравно, это был только совет.
Ну это вообще пЪять! Компьютер слишком сложный, и поэтому нестабильный, и ну его нафиг! На счётах (деревянных) надо считать, господа, на счётах!
Y_Mur Лично мне, как бегиннерсу, всегда нравилась возможность уничтожить всю свою кучу целиком после работы, чем освобождать каждый участочек по 8-10 байт из дефолтной. Как пример - собрать список файлов в строку. Пока проходимся по FindNextFile, выделяем по чуть-чуть из кучи, составляя связный список. А потом всё, что насобирали, переписываем в сплошную область памяти. Так вот ИМХО после сбора списка легче удалить всю кучу сразу, чем каждое имя файла по одному из дефолтной кучи удалять.
А нахрена? Проще же вообще рестартануть процесс - и всех делов, все лишние ресурсы освобождены! А если серьезно, то описанный тобой подход работает лишь в простейшем случае, когда память выделяется для примитивных данных. В реальности же память чаще выделяется под объекты. И если удалить весь хип, то деструкторы этих объектов вызваны не будут, что может привести к самым неожиданным багам