VirtualAlloc must die ?????

Тема в разделе "WASM.WIN32", создана пользователем S_T_A_S_, 5 фев 2005.

  1. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Не пойму, то ли меня клинит, то ли нет %)

    Уже голову сломал, зачем нужна эта функция ?????



    (RTFMSDN читал, вопрос не в этом :)

    Вопрос филосовский: Нужна ли?



    Простой пример: есть exe, который использует для своих нужд буфер 20 метров, например, хранит там каие-то данные.



    Вот какие аргументы "за использование VirtualAlloc" я нашёл:

    - так написано у Рихтера;

    - так все делают;

    - ?????



    Да, но можно так же использовать секцию неинициализированных данных PE файла.

    Что это даёт:

    - адреса фиксированны и известны на стадии компиляции, что делает работу с памятью проще;

    - поскольку адреса известны, это можно использовать в своих целях: контроль поинтеров, сборка мусора и т.п.

    - и вообще, проще работа - меньше ашипок...



    При этом поведение секции PE и аллоцированной памяти в принципе одинаково, фактически VirtualAlloc делает загрузчик.



    Конечно, можно найти специфические случаи, когда нужна именно VirtualAlloc, но в таких вот простейших, зачем оно надо?



    Хотелось бы услышать мнение Дзенствующих по этому поводу.
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    S_T_A_S_

    Простой приемр: Текстовый редактор. Открываем файл. Его размера мы не знаем. Отсюда вывод - либо юзаем Virtual/Global/Heap Alloc, либо придется придумать максимальный размер файла. Пусть это 25.6 метров при 256-ти ОЗУ. Получается, не получится редактировать более 10-ти файлов по 1Кб.
     
  3. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    _DEN_



    GlobalAlloc НЕ юзаем совсем никогда, это не от той ОСи про которую речь.

    Про файл я прекрасно понимаю, речь не об этих "специфических" случаях.



    ты в своей проге plasma_fast.cpp использовал:
    Код (Text):
    1.  
    2. #define GRID_X 32
    3. #define GRID_Y 32
    4. Color=new float[1000*GRID_X*GRID_Y*3];


    А я говорю, что можно так:
    Код (Text):
    1. static float Color[1000*GRID_X*GRID_Y*3];
     
  4. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    S_T_A_S_





    Почему?







    Если так судить то все случаи специфичны. Где-то удобнее юзать Alloc, где-то неинициализированные данные.



    Alloc это повышение уровня абстракции, отсутствие привязки к формату exe-шника.
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Вобщем, мой ответ такой:

    VirtualAlloc must die, если ты сразу знаешь размер массива, размер не будем меняться и массив будет нужен всю программу. В противном случае - VirtualAlloc forever.
     
  6. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    S_T_A_S_

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

    Можно конечно организовать свой менеджер памяти, работающий в рамках секции неинициализированных данных, но зачем если система дает готовый.
     
  7. cresta

    cresta Active Member

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

    .data?

    BBBB dd 1000000 dup(?)



    Такая строка загоняет линкера в тупик, и он не выходит из него ...много времени, я ждал 7 мин. - не дождался, пришлось пристрелить его.



    100000 dup(?) - задумывается секунд на 10-12.
     
  8. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    cresta

    Это не тупик. Это бага MASM-овского линкера. Время линковки у него какого-то хрена квадратично от размера.

    Юзай FASM :)
     
  9. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    _DEN_ >




    дочитай мой первый ответ ДО конца ;)





    green >




    Вот, это уже ответ по теме :).

    Да, опасно что слишком большой виртуальный размер секции может привести к тому, что система не сможет загрузить PE.

    Хотя с другой стороны возможна и обратная ситуация: система не сможет выделить непрерывный блок памяти при вызове VirtualAlloc.

    Думаю последнее всё-таки менее вероятно, т.к. базовый адрес экзешника фиксирован (обычно), а аллоцировать можно память по любому адресу.



    Видимо существует какой-то разумный предел, больше которого резмер секции просто не стОит делать, причём самое плохое - он будет разный для разных систем :-(

    О том, что размер секции больше, чем может понадобиться, imho можно не бояться - пока к странице нет обращений физическая память выделяться не будет.



    >




    Это вопрос скорости. Система предоставляет универсальный, а значит не максимално эффективный менеджер. Тут простая арифметика: или читаем откуда-то из памяти поинтер + косвенное обращение к памяти, или адрес является непосредственным операндом.





    cresta >




    Это не линкер, а ассемблер (ml.exe), можно создать объектник FASM'ом или MSVC, который такого глюка не имеет.
     
  10. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine


    При динамическом распределении адресс данных будет переменным даже при использовании собственного менеджера.
     
  11. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    ну в общем, да, хотя переменных составляющих там всё же будет меньше.
     
  12. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Я готовлю статейку по менеджеру памяти для своего сайта. Исходный код (С++) будет приложен, ну и для любителей FASM-а постараюсь сделать код. Единственное, что: статья на английском - нет времени на перевод.



    В API есть HeapAlloc(), но проблема там в том, что каждая функция заботится о нескольких thread-ах выполнения. Общий случай кода, как кто-то верно подметил. И конечно это замедляет код.
     
  13. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    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.
     
  14. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    S_T_A_S_





    Всеравно не понял! :))
     
  15. _Juicy

    _Juicy Active Member

    Публикаций:
    0
    Регистрация:
    12 авг 2003
    Сообщения:
    1.159
    Адрес:
    SPb
    S_T_A_S_

    Ты когда-нить занимался разработкой/изучением серьезных вещей? Вовсе не исключительная, а самая частая ситуация такова: поток должен выполнить некоторую задачу, он собирает данные и запихивает их в участок памяти. В это же время другому потоку нужно выполнить ту же самую задачу. Что он должен делать? Ждать первый поток? К черту многозадачность?

    Так вот в нормальном случае каждый поток выделяет себе участок памяти и хранит указатель на него в своем стеке. А как ты сделаешь это если все потоки хотят пихнуть данные по одному адресу?

    И в случае с
    Код (Text):
    1. static float Color[1000*GRID_X*GRID_Y*3];


    все рухнет, стоит только сделать приложение многопоточным.
     
  16. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine


    _Juicy

    Многопоточность не обязательно предполагает использование виндовых Alloc-ов.

    Во-первых во многих случаях достаточно стэка.



    Во-вторых, например, можно хранить данные для каждого потока в статическом массиве (конечно макс. кол. потоков и размер данных при этом есть константы времени компиляции).

    Правда для работы с таким массивом придется написать код типа простого менеджера динамической памяти. :)
     
  17. _Juicy

    _Juicy Active Member

    Публикаций:
    0
    Регистрация:
    12 авг 2003
    Сообщения:
    1.159
    Адрес:
    SPb
    Во-вторых, например, можно хранить данные для каждого потока в статическом массиве

    Ну да, а некоторые картошку с сахаром едят...

    Но для серьезных приложений ни стек, ни тем более статический массив не подойдут.
     
  18. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine


    а что, тоже дзен !

    :)
     
  19. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    _DEN_ >




    RTFMSDN:



    А по-русски - это ф-ция win3.1





    semen >




    Угу. ТОЛЬКО один нюанс - не принудительно приводить, а использовать это по мере возможностей



    >




    Понятно, что это опасно.

    Я думаю 20-50 метров можно запросто делать.



    Хотя прямо сейчас у меня работает прога гда VirtualSize одной из секций = 0x20000000

    директх пока не загнулся :).



    В разных запакованных прогах сплошь и рядом используют просто огромные секции для разных некошерных целей.





    _Juicy >




    ну.. это же не является "простейшим случаем" о которых я говорю :).

    Хотя если заранее известно количество потоков, то никаких проблем:

    поток №1 оспользует первый метр, поток №2 использует 2й метр и т.д.

    Если код этих потоков _различный_, то это укладывается в мою модель,

    если же _одинаковый_ - никакого выигрыша не будет поскольку нельзя использовать фиксированные адреса данных, и тогда логичнее делать VirtualAlloc



    >




    Не рухнет, да же если сделать - см. исходник (хотя там многопоточность совсем ни к чему)

    Это как раз это хороший пример, когда динамическое аллоцирование не нужно, но его зачем-то используют.



    >




    Возмём, например, сам виндос.

    Использует глобальную таблицу объектов GDI которая находится по фиксированному адресу.
     
  20. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев


    Бред. Я всегда так делаю. У меня размер данных может меняться в очень широких пределах в некоторых процедурах - от 1 кб до десятков мб. делаю коммит на максимальный размер, ставлю seh, ловлю по этому адресу исключение и делаю этому блоку relese.