Задача такая Есть массив вордов (unsigned short) При чем начальное количество вордов, которое будет помещено в этот массив неизвестно. Может быть 1, а может и 1 млн. Хочется сделать буффер, который будет расширяться, в зависимости от количества положенных в него элементов. Как со стеком в общем-то. Т.е. превысили границу - бамс! выделена новая 4х килобайтная страница из резервной области. Подскажите, как лучше реализовать подобное. Заранее благодарен
В общем-то, память можно даже и не выделять. Т.е. тупо брать указатель на начало хипа и творить все свои чёрные дела без разрешения Винды =) Однако это накладывает серьёзные ограничения на использование API функций, работающих с хипом проги - они могут легко затереть нужные данные. Поэтому пользовать их надо очень осторожно. А лучше в таком случае вообще не пользовать...
DEEP нет, не устраивает. Тот же стек заюзать я и сам мог бы. Или хип. Но дело в том, что пишу модуль, а не приложение. И при таком подходе - креш - вопрос времени. Velheart Подробнее пожалуйста.
Magnum http://msdn.microsoft.com/en-us/library/bb386284.aspx Позволяет динамически увеличивать размер массива, только обманчиво-простые конструкции сишного кода потом компилируются в громоздко-педальные ассемблерные =)
Magnum вкратце: STL-контейнеры управляют памятью автоматически, используя указанный в конструкторе контейнера аллокатор, который, если его не указывать, используется дефолтный определенный для вектора (ну или какой там контейнер вы используете). если не устраивает дефолтный, то можно создать свой аллокатор и указать контейнеру использовать его для работы с память. по-дефолту аллокатор вектора устроен так, что удваивает свой буфер по заполнению текущего буфера под завязку. для большинства потребностей этого дефолтного аллокатора хватает. но никто не мешает указать вектору использовать наш свой, собственный аллокатор, который для работы с памятью использует свою собственную стратегию. помимо этого можно поэкспериментировать с пулами из boost (http://boost.org). к примеру для вектора можно использовать в кач-ве аллокатора boost::pool_allocator также, прирост в производительности может дать зарезервирование заранее места под элементы контейнера, если заранее известно сколько примерно их может быть. тем самым кол-во аллоцирований новых блоков памяти и переаллокации заметно уменьшаются. (для вектора это vector.reserve(size)). слету использовать std::vector я бы не стал. поэкспериментируй, позамеряй работу и с др. STL-контейнерами (тот же std::list, std::deque). не факт что для твоей задачи 100% вектор будет оптимальным решением.
Magnum чуть поподробнее о предназначении буффера. Ваша прога в него пишет и читает. Или хоть с одного конца внешние проги/либы висят? Или еще как?
Magnum есть хорошая книжка по стратегиям управления памятью в С++ (если поверхностная работа с STL-контейнерами не вдаваясь в их работу с памятью не устраивает). называется: "Memory management: Algorithms and implementation in C/C++", автор "Blunden B.". в ней описаны хорошо с примерами несколько стратегий по работе с памятью в С++. ps: и еще, не забудь предусмотреть корректное освобождение выделенной памяти. если будешь хранить в контейнере указатели -- контейнер за тебя память эту не освободит извиняюсь, если вдаюсь в ненужные подробности.
Magnum Прежде чем что-то критиковать, хорошо бы хотя бы примерно представлять себе о чем идет речь. Требования, предъявляемые C++ TR1 к std::vector делают его гораздо более подходящим и стабильным чем все это "системно-апишное" подростковое баловство.
Magnum если оптимизация по скорости, то выделить память под динамический массив указателей на начало каждого маленького буффера (одинакового размера), память выделять под такие кусочки буффера динамически средствами ОС. а для удобства в отдельной переменной хранить количество выделенных буферов.
Magnum Тфу ты... Я дико извиняюсь - в пятницу вечером я уже был даже не в состоянии отличить DEEP от Velheart. Прошу прощения, я просто перепутал авторов и мне показалось совсем не то, что было написано на самом деле.
AsmGuru62 Дык оно ясен пень! Однако при "надстраивании" буфера (в отличие от его урезания), он постоянно будет переноситься в новое месторасположение! И облать "пустого" хипа, оставшегося от прошлых переносов, будет совершенно некошерным образом расти. Я поэтому и предлагал обойтись вообще без аллоков. Представим: Код (Text): Есть у нас хип. Вот он: __________________________________ |__________________________________ ••• Мы из него выделяем, напр, пять двордов: ____________________________ |99999|____________________________ Хотим надстроить буфер ещё штуки на три, и что делает нам ReAlloc? _____ ___________________ |_____|99999999|___________________ Он переносит исходный кусок в позицию, идущую после евойного конца, и освобождает исходные пять. В итоге первые пять двордов остаются невостребованными. А ещё плюс ко всему на перенос памяти тратится немало процессорного времени. ИМХО, так делать можно. Но это нерационально.
А почему бы не выделять памяти на 10% больше, чем требуется, чтоб потом с добавлением проблем не было. Могу привести пример, но не думаю, что все здесь фанаты LocalAlloc(LMEM_FIXED,...) и ассемблера.
Делаешь VirtualAlloc c MEM_RESERVE на макс. размер, который тебе понадобится - на 512мб например. Этот вызов зарезервирует тебе диапазон адресов в адресном пространстве твоего процесса А потом уже можешь выделять память тем же VirtualAlloc с нужного адреса и нужного размера выделяешь 128К с начала, закончились - выделяешь следующие 128К.... быстро работает, не жрет лишнюю оперативу, никакой фрагментации памяти. ЗЫ: в Линуксе наверняка есть похожий механизм, но я с ним не знаком