Как создать резиновый буффер ?

Тема в разделе "LANGS.C", создана пользователем Magnum, 12 сен 2008.

  1. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Задача такая
    Есть массив вордов (unsigned short)
    При чем начальное количество вордов, которое будет помещено в этот массив неизвестно.
    Может быть 1, а может и 1 млн.

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

    Как со стеком в общем-то.
    Т.е. превысили границу - бамс! выделена новая 4х килобайтная страница из резервной области.

    Подскажите, как лучше реализовать подобное.

    Заранее благодарен
     
  2. DEEP

    DEEP Андрей

    Публикаций:
    0
    Регистрация:
    27 апр 2008
    Сообщения:
    491
    Адрес:
    г. Владимир
    В общем-то, память можно даже и не выделять. Т.е. тупо брать указатель на начало хипа и творить все свои чёрные дела без разрешения Винды =)
    Однако это накладывает серьёзные ограничения на использование API функций, работающих с хипом проги - они могут легко затереть нужные данные. Поэтому пользовать их надо очень осторожно. А лучше в таком случае вообще не пользовать...
     
  3. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Так есть же vector STL-ный, или он чем-то не устраивает ?
     
  4. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    DEEP
    нет, не устраивает.
    Тот же стек заюзать я и сам мог бы. Или хип. Но дело в том, что пишу модуль, а не приложение.
    И при таком подходе - креш - вопрос времени.

    Velheart
    Подробнее пожалуйста. :)
     
  5. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Magnum
    http://msdn.microsoft.com/en-us/library/bb386284.aspx
    Позволяет динамически увеличивать размер массива, только обманчиво-простые конструкции сишного кода потом компилируются в громоздко-педальные ассемблерные =)
     
  6. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Magnum
    вкратце: STL-контейнеры управляют памятью автоматически, используя указанный в конструкторе контейнера аллокатор, который, если его не указывать, используется дефолтный определенный для вектора (ну или какой там контейнер вы используете). если не устраивает дефолтный, то можно создать свой аллокатор и указать контейнеру использовать его для работы с память.
    по-дефолту аллокатор вектора устроен так, что удваивает свой буфер по заполнению текущего буфера под завязку. для большинства потребностей этого дефолтного аллокатора хватает. но никто не мешает указать вектору использовать наш свой, собственный аллокатор, который для работы с памятью использует свою собственную стратегию.

    помимо этого можно поэкспериментировать с пулами из boost (http://boost.org).
    к примеру для вектора можно использовать в кач-ве аллокатора
    boost::pool_allocator

    также, прирост в производительности может дать зарезервирование заранее места под элементы контейнера, если заранее известно сколько примерно их может быть. тем самым кол-во аллоцирований новых блоков памяти и переаллокации заметно уменьшаются. (для вектора это vector.reserve(size)).

    слету использовать std::vector я бы не стал. поэкспериментируй, позамеряй работу и с др. STL-контейнерами (тот же std::list, std::deque). не факт что для твоей задачи 100% вектор будет оптимальным решением.
     
  7. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    Magnum
    чуть поподробнее о предназначении буффера. Ваша прога в него пишет и читает. Или хоть с одного конца внешние проги/либы висят? Или еще как?
     
  8. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    Velheart, varnie
    спасибо большое!!!
     
  9. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    Magnum
    есть хорошая книжка по стратегиям управления памятью в С++ (если поверхностная работа с STL-контейнерами не вдаваясь в их работу с памятью не устраивает).
    называется: "Memory management: Algorithms and implementation in C/C++", автор "Blunden B.". в ней описаны хорошо с примерами несколько стратегий по работе с памятью в С++.

    ps: и еще, не забудь предусмотреть корректное освобождение выделенной памяти. если будешь хранить в контейнере указатели -- контейнер за тебя память эту не освободит:)
    извиняюсь, если вдаюсь в ненужные подробности.
     
  10. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    varnie
    спасибо
    поставил на закачку
    на английском правда
    сейчас ищу перевод на русский
     
  11. _DEN_

    _DEN_ DEN

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

    Прежде чем что-то критиковать, хорошо бы хотя бы примерно представлять себе о чем идет речь. Требования, предъявляемые C++ TR1 к std::vector делают его гораздо более подходящим и стабильным чем все это "системно-апишное" подростковое баловство.
     
  12. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    У Рихтера про это тоже есть просто, доступно, классически и переведено на русский на С++ + API
     
  13. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    Magnum
    если оптимизация по скорости, то выделить память под динамический массив указателей на начало каждого маленького буффера (одинакового размера), память выделять под такие кусочки буффера динамически средствами ОС.
    а для удобства в отдельной переменной хранить количество выделенных буферов.
     
  14. Magnum

    Magnum New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2007
    Сообщения:
    925
    _DEN_

    Где в моем посте вы узрели критику std ?? ))
     
  15. _DEN_

    _DEN_ DEN

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

    Тфу ты... Я дико извиняюсь - в пятницу вечером я уже был даже не в состоянии отличить DEEP от Velheart. Прошу прощения, я просто перепутал авторов и мне показалось совсем не то, что было написано на самом деле.
     
  16. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Можно, в принципе, использовать HeapReAlloc().
     
  17. DEEP

    DEEP Андрей

    Публикаций:
    0
    Регистрация:
    27 апр 2008
    Сообщения:
    491
    Адрес:
    г. Владимир
    AsmGuru62
    Дык оно ясен пень! Однако при "надстраивании" буфера (в отличие от его урезания), он постоянно будет переноситься в новое месторасположение! И облать "пустого" хипа, оставшегося от прошлых переносов, будет совершенно некошерным образом расти. Я поэтому и предлагал обойтись вообще без аллоков. Представим:

    Код (Text):
    1. Есть у нас хип. Вот он:
    2.  __________________________________
    3. |__________________________________ •••
    4.  
    5.  
    6. Мы из него выделяем, напр, пять двордов:
    7.        ____________________________
    8. |99999|____________________________
    9.  
    10.  
    11. Хотим надстроить буфер ещё штуки на три, и что делает нам ReAlloc?
    12.  _____          ___________________
    13. |_____|99999999|___________________
    14.  
    15. Он переносит исходный кусок в позицию, идущую после евойного конца, и освобождает исходные пять.
    16.  
    17.  
    18. В итоге первые пять двордов остаются невостребованными.
    А ещё плюс ко всему на перенос памяти тратится немало процессорного времени.
    ИМХО, так делать можно.
    Но это нерационально.
     
  18. slavanap

    slavanap Вячеслав

    Публикаций:
    0
    Регистрация:
    10 сен 2008
    Сообщения:
    300
    Адрес:
    Смоленск, Россия
    А почему бы не выделять памяти на 10% больше, чем требуется, чтоб потом с добавлением проблем не было.
    Могу привести пример, но не думаю, что все здесь фанаты LocalAlloc(LMEM_FIXED,...) и ассемблера.
     
  19. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    Делаешь VirtualAlloc c MEM_RESERVE на макс. размер, который тебе понадобится - на 512мб например.
    Этот вызов зарезервирует тебе диапазон адресов в адресном пространстве твоего процесса
    А потом уже можешь выделять память тем же VirtualAlloc с нужного адреса и нужного размера
    выделяешь 128К с начала, закончились - выделяешь следующие 128К....
    быстро работает, не жрет лишнюю оперативу, никакой фрагментации памяти.
    ЗЫ: в Линуксе наверняка есть похожий механизм, но я с ним не знаком