Не пойму, то ли меня клинит, то ли нет %) Уже голову сломал, зачем нужна эта функция ????? (RTFMSDN читал, вопрос не в этом Вопрос филосовский: Нужна ли? Простой пример: есть exe, который использует для своих нужд буфер 20 метров, например, хранит там каие-то данные. Вот какие аргументы "за использование VirtualAlloc" я нашёл: - так написано у Рихтера; - так все делают; - ????? Да, но можно так же использовать секцию неинициализированных данных PE файла. Что это даёт: - адреса фиксированны и известны на стадии компиляции, что делает работу с памятью проще; - поскольку адреса известны, это можно использовать в своих целях: контроль поинтеров, сборка мусора и т.п. - и вообще, проще работа - меньше ашипок... При этом поведение секции PE и аллоцированной памяти в принципе одинаково, фактически VirtualAlloc делает загрузчик. Конечно, можно найти специфические случаи, когда нужна именно VirtualAlloc, но в таких вот простейших, зачем оно надо? Хотелось бы услышать мнение Дзенствующих по этому поводу.
S_T_A_S_ Простой приемр: Текстовый редактор. Открываем файл. Его размера мы не знаем. Отсюда вывод - либо юзаем Virtual/Global/Heap Alloc, либо придется придумать максимальный размер файла. Пусть это 25.6 метров при 256-ти ОЗУ. Получается, не получится редактировать более 10-ти файлов по 1Кб.
_DEN_ GlobalAlloc НЕ юзаем совсем никогда, это не от той ОСи про которую речь. Про файл я прекрасно понимаю, речь не об этих "специфических" случаях. ты в своей проге plasma_fast.cpp использовал: Код (Text): #define GRID_X 32 #define GRID_Y 32 Color=new float[1000*GRID_X*GRID_Y*3]; А я говорю, что можно так: Код (Text): static float Color[1000*GRID_X*GRID_Y*3];
S_T_A_S_ Почему? Если так судить то все случаи специфичны. Где-то удобнее юзать Alloc, где-то неинициализированные данные. Alloc это повышение уровня абстракции, отсутствие привязки к формату exe-шника.
Вобщем, мой ответ такой: VirtualAlloc must die, если ты сразу знаешь размер массива, размер не будем меняться и массив будет нужен всю программу. В противном случае - VirtualAlloc forever.
S_T_A_S_ IMHO, в простейших случаях в самом деле можно обойтись без динамически выделяемой памяти. Но в реальных программах очень часто приходится иметь дело с данными размер которых неизвестен на этапе компиляции. Делать запас по максимуму - слишком расточительно. Можно конечно организовать свой менеджер памяти, работающий в рамках секции неинициализированных данных, но зачем если система дает готовый.
Один маленький минус: .data? BBBB dd 1000000 dup(?) Такая строка загоняет линкера в тупик, и он не выходит из него ...много времени, я ждал 7 мин. - не дождался, пришлось пристрелить его. 100000 dup(?) - задумывается секунд на 10-12.
cresta Это не тупик. Это бага MASM-овского линкера. Время линковки у него какого-то хрена квадратично от размера. Юзай FASM
_DEN_ > дочитай мой первый ответ ДО конца green > Вот, это уже ответ по теме . Да, опасно что слишком большой виртуальный размер секции может привести к тому, что система не сможет загрузить PE. Хотя с другой стороны возможна и обратная ситуация: система не сможет выделить непрерывный блок памяти при вызове VirtualAlloc. Думаю последнее всё-таки менее вероятно, т.к. базовый адрес экзешника фиксирован (обычно), а аллоцировать можно память по любому адресу. Видимо существует какой-то разумный предел, больше которого резмер секции просто не стОит делать, причём самое плохое - он будет разный для разных систем :-( О том, что размер секции больше, чем может понадобиться, imho можно не бояться - пока к странице нет обращений физическая память выделяться не будет. > Это вопрос скорости. Система предоставляет универсальный, а значит не максимално эффективный менеджер. Тут простая арифметика: или читаем откуда-то из памяти поинтер + косвенное обращение к памяти, или адрес является непосредственным операндом. cresta > Это не линкер, а ассемблер (ml.exe), можно создать объектник FASM'ом или MSVC, который такого глюка не имеет.
При динамическом распределении адресс данных будет переменным даже при использовании собственного менеджера.
Я готовлю статейку по менеджеру памяти для своего сайта. Исходный код (С++) будет приложен, ну и для любителей FASM-а постараюсь сделать код. Единственное, что: статья на английском - нет времени на перевод. В API есть HeapAlloc(), но проблема там в том, что каждая функция заботится о нескольких thread-ах выполнения. Общий случай кода, как кто-то верно подметил. И конечно это замедляет код.
S_T_A_S_ Наскока я понял, тебе хочется свести свою прогу к виду: pMem = (BYTE*)VirtualAlloc(0, MemSize, MEM_COMMIT, PAGE_READWRITE); и НИГДЕ больше не использовать выделение памяти + убрать сам VirtualAlloc и вместо pMem использовать BSS секцию. Чтож флаг в руки - никто не мешает. Но ты забывашь, что при использовании, где это реально надо, у VirtualAlloc параметры flAllocationType и flProtect не всегда MEM_COMMIT и PAGE_READWRITE, а виртуальное адресное пространство процесса - такой же ресурс и его надо экономить. Кстати, VirtualAlloc помоему вообще надо использовать, когда надо\есть возможность работать на уровне страниц. Когда "есть возможность" - это экономит скорость, т.к. страничная аллокация наиболее быстрая. Ну а когда "надо" - тогда надо , например для защиты памяти. Когда надо работать не на уровне страниц - тогда хипы, можно виндовые(обычно этого хватает для большинства задач и оптимизировать там нечего - выиграша не будет), или можно как ты говорил, сделать свой. Но не надо сразу хавать все виртуальное пространство - т.к. это может негативно сказаться на перфомансе\работоспособности системы - она ведь переодически делает трим воркинг сета процесса и т.д. - мало ли что еще станет делать в будущем, или директх загнется от такого издевательства. Мораль - не юзай ресурсов больше чем надо, оптимизируй тока тогда, когда в этом есть реальная необходимость. Мне например действительно приходилось оптимизировать работу с памятью, когда делал поисковик. AsmGuru62 Помойму в виндовом хипе,при создании хипа можно отключить поддержку мультитреда, а так-же установить флаг low fragmentation heap.
S_T_A_S_ Ты когда-нить занимался разработкой/изучением серьезных вещей? Вовсе не исключительная, а самая частая ситуация такова: поток должен выполнить некоторую задачу, он собирает данные и запихивает их в участок памяти. В это же время другому потоку нужно выполнить ту же самую задачу. Что он должен делать? Ждать первый поток? К черту многозадачность? Так вот в нормальном случае каждый поток выделяет себе участок памяти и хранит указатель на него в своем стеке. А как ты сделаешь это если все потоки хотят пихнуть данные по одному адресу? И в случае с Код (Text): static float Color[1000*GRID_X*GRID_Y*3]; все рухнет, стоит только сделать приложение многопоточным.
_Juicy Многопоточность не обязательно предполагает использование виндовых Alloc-ов. Во-первых во многих случаях достаточно стэка. Во-вторых, например, можно хранить данные для каждого потока в статическом массиве (конечно макс. кол. потоков и размер данных при этом есть константы времени компиляции). Правда для работы с таким массивом придется написать код типа простого менеджера динамической памяти.
Во-вторых, например, можно хранить данные для каждого потока в статическом массиве Ну да, а некоторые картошку с сахаром едят... Но для серьезных приложений ни стек, ни тем более статический массив не подойдут.
_DEN_ > RTFMSDN: А по-русски - это ф-ция win3.1 semen > Угу. ТОЛЬКО один нюанс - не принудительно приводить, а использовать это по мере возможностей > Понятно, что это опасно. Я думаю 20-50 метров можно запросто делать. Хотя прямо сейчас у меня работает прога гда VirtualSize одной из секций = 0x20000000 директх пока не загнулся . В разных запакованных прогах сплошь и рядом используют просто огромные секции для разных некошерных целей. _Juicy > ну.. это же не является "простейшим случаем" о которых я говорю . Хотя если заранее известно количество потоков, то никаких проблем: поток №1 оспользует первый метр, поток №2 использует 2й метр и т.д. Если код этих потоков _различный_, то это укладывается в мою модель, если же _одинаковый_ - никакого выигрыша не будет поскольку нельзя использовать фиксированные адреса данных, и тогда логичнее делать VirtualAlloc > Не рухнет, да же если сделать - см. исходник (хотя там многопоточность совсем ни к чему) Это как раз это хороший пример, когда динамическое аллоцирование не нужно, но его зачем-то используют. > Возмём, например, сам виндос. Использует глобальную таблицу объектов GDI которая находится по фиксированному адресу.
Бред. Я всегда так делаю. У меня размер данных может меняться в очень широких пределах в некоторых процедурах - от 1 кб до десятков мб. делаю коммит на максимальный размер, ставлю seh, ловлю по этому адресу исключение и делаю этому блоку relese.