|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
12.09.2009, 13:12 | #1 |
В тени
Старожил
Регистрация: 19.12.2008
Сообщений: 5,788
|
Своя реализация malloc и free
Дали мне тут одно задание - реализовать свои malloc и free. Естественно, не пользуясь стандартными.
Мне дано 10 метров памяти (статический массив). Собственно, программа уже сделана и работает. Но показать преподавателю могу только на следующей неделе, поэтому пока есть время порассуждать. Итак, описываю, как сделал я. Есть массив ALLBUF размером в 10 Мб. static char ALLBUF[BUF_SIZE]; Это и будет моя виртуальная память. Есть две пары массивов: static char* pools[MAX_POOLS] - массив адресов свободных пулов, то есть свободных участков памяти. static unsigned int pools_size[MAX_POOLS] - массив, который хранит размеры этих пулов. static char* blocks[MAX_POOLS] - массив адресов блоков (занятых участков). static unsigned int block_size[MAX_POOLS] - их размеры. И есть еще переменная RIGHT_BLOCK, которая указывает (хранит номер) на самый правый блок. MAX_POOLS - максимальное количество блоков или пулов (сделал 1000). Функции (описываю не все, а основные): void ars_alloc_init(void) - присваивает первому элементу массива пулов адрес начала массива ALLBUF, а также заносит его размер (10 Мб) в соответствующий элемент массива размеров. Эта функция вызывается первой в тестовой программе. char* ars_malloc(unsigned long Size) Функция выделения. Если требуют больше, чем есть - возвращает 0. Если нет пула достаточного размера - возвращаем 0. Если все ок, то добавляем в массив блоков адрес первого подошедшего пула. Увеличиваем количество блоков (BLOCKS_COUNT) и RIGHT_BLOCK. Пул, в котором разместили блок, теперь начинается в конце этого блока. Возвращаем указатель на блок. int ars_free(char* block) Функция освобождения. Ищем блок по адресу в массиве blocks. Если не нашли - выходим. Если нашли, то зануляем блок, уменьшаем количество блоков (при этом RIGHT_BLOCK не меняется), добавляем в массив пулов адрес бывшего блока. Такой подход очень неэффективен, т.к. память быстро фрагментируется. После нескольких выделений/освобождений появляются смежные пулы, которые хорошо бы объединить. Поэтому я добавил функцию дефрагментации, которая смещает все блоки влево, вплотную друг к другу. Была идея при освобождении искать адрес ближайшего левого пула, и если он ближе, чем ближайший левый блок, объединять новый пул с найденным (ну и с правой стороной также). Но как-то мне она не очень понравилась. ------------------- Собственно, программу написал за вечер, взял первую идею, что пришла в голову. Мне не нравится, что помимо основной памяти (виртуальной - ALLBUF) приходится использовать еще достаточное количество для массивов адресов и размеров. Притом они еще и статические, поэтому приходится также ограничивать количество элементов. ---------- Интересно будет послушать другие идеи. Код не выкладываю, т.к. врядли кому-нибудь интересно его читать. А его словесное описание - выше.
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем. ___________________________________ ___________________________________ _______ [=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль] Последний раз редактировалось Sazary; 12.09.2009 в 13:24. |
12.09.2009, 13:39 | #2 |
Eclipse Foundation
Старожил
Регистрация: 19.09.2007
Сообщений: 2,604
|
Все пулы одинакового размера или каждый пул имеет такой размер, какой занимает в нем информация?
Последний раз редактировалось MaTBeu; 12.09.2009 в 13:42. |
12.09.2009, 13:40 | #3 |
Пользователь
Регистрация: 12.10.2007
Сообщений: 32
|
Сделано грамотно, есть схожесть в менеджером памяти WinXP=)
А теперь - зачем при вызове int ars_free(char* block) занулять память? Уж лучше тогда при выделении обнулять... Да и то, если юзеру надо сам обнулит... И еще, зачем хранить длину блока памяти, не лешче ли хранить кол-во блоков?
Si vis pacem, para bellum!
|
12.09.2009, 13:46 | #4 | |||
В тени
Старожил
Регистрация: 19.12.2008
Сообщений: 5,788
|
Цитата:
То есть, например, выделили память под блок - размер пула уменьшился, а адрес его начала сместился. Потом выделили второй блок, а первый освободили. В итоге имеем 2 пула - один в начале (до второго блока), второй - в конце. Цитата:
Цитата:
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем. ___________________________________ ___________________________________ _______ [=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль] |
|||
12.09.2009, 14:36 | #5 |
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
я так понимаю информация между массивами pools, pools_size перекочевывает в blocks, block_size при malloc и наоборот при free? Это же долго будет массив "сдвигаться", чтобы удалить центральный элемент из него.
Я бы пожалуй реализовал примерно таким образом: структура "блок памяти", хранящий начальный адрес и размер. Соответственно, массив этих самых блоков памяти. Свободные участки реализовал бы по типу односвязного списка (хотя может и на массиве оставил, тут думать надо и взвешивать все за и против ) и упорядочил по размеру блока (потому что достаточно важно использовать наиболее подходящий по размеру блок, чтобы не "резать" первый попавшийся, что в итоге окажется куча мелких блоков, в которые ничего не влезет). Размер и адрес для участка отдельно хранить бы не стал, а тупо ссылался на элемент общего массива блоков. Выделенную память по тому же образу бы пожалуй хранил, но упорядочил уже по адресу, т.к. освобождается она именно по адресу. Поддержание списка в отсортированном виде достаточно "дешево", но зато поиск потом будет шустрее работать. На массивах конечно это будет слишком дорого. Вообще тут можно много чего напридумывать и лично мне очень сложно сделать выбор между занимаемой памятью и скоростью работы. Так и хочется хранить массив занятых блоков памяти, где индексом является адрес блока. Удаление будет моментальным, но на 10 метров "полезной" памяти будет в N-цать раз больше служебных данных храниться |
12.09.2009, 15:01 | #6 | |
В тени
Старожил
Регистрация: 19.12.2008
Сообщений: 5,788
|
Цитата:
Т.к. мне нужно вернуть указатель на выделенную память, то просто как-то не вижу смысла создавать отдельную структуру. Проще, по-моему, использовать память как единый блок. Ведь блоки все равно нельзя держать в разных местах. Сделать сортировку пулов по размеру, конечно, хорошо, но ведь как-то не очень эффективно с точки зрения скорости. Собственно, вот код. Выкладываю, чтобы показать, что в функциях malloc и free все операции только над указателями. Скорость за счет фрагментации. Код:
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем. ___________________________________ ___________________________________ _______ [=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль] |
|
12.09.2009, 15:14 | #7 | |
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
Цитата:
Зато поиск по отсортированной последовательности в разы быстрее, чем простой линейный перебор. Такую штуку конечно тестить нужно в идеале по взрослому. С профайлерами всякими. Занять всю память маленькими элементами, потом всё освободить и попытаться выделить под большие блоки, т.е. нужно делать поддержку "склеивания" свободных блоков. Блин. Аж интересно стало как оно на практике это всё будет, что хоть тоже реализовывай Ну а в целом, идея вроде неплохая и как учебный проект сойдёт. В реале еще и многопоточность появится в списке проблем |
|
12.09.2009, 15:25 | #8 |
В тени
Старожил
Регистрация: 19.12.2008
Сообщений: 5,788
|
Нечто среднее между списком и массивом? )
Но тогда нужно будет для единичного блока какой-то размер выбрать (>1), ведь если взять 1 байт, то это будет как-то расточительно (в структуре будет один элемент в 1 байт (для информации) и как минимум еще 4б под указатель на след. элемент). Но тогда такая проблема будет: а если юзер захочет выделить несколько участков по 1 байту? Ведь тогда все равно придется отдавать по целому блоку. Значит, как я понял, склеивание лучше все-таки добавить? Лучше смотреться будет? Всякие профайлеры я, конечно, использовать не буду Да это и не проект скорее, а так.. Что-то поменьше. Все должны сделать 3 лабы на ввод-вывод-ветвления, а мне вот это дали
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем. ___________________________________ ___________________________________ _______ [=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль] |
12.09.2009, 15:42 | #9 | ||||
Старожил
Регистрация: 22.05.2007
Сообщений: 9,065
|
Цитата:
Цитата:
Цитата:
Так вот "на глаз" и не определишь просто что будет оптимальнее: дефрагментация по мере необходимости или же частичная дефрагментация "на лету", путём склеивания соседних свободных блоков памяти. Цитата:
Если задача интересна как программисту, то есть над чем подумать и улучшить, ну а если чисто для галочки в журнале препода - то вполне неплохо. В конце концов: зачем париться с какой-то "левой" задачей, если это время можно потратить на что-то более интересное. |
||||
12.09.2009, 15:56 | #10 |
В тени
Старожил
Регистрация: 19.12.2008
Сообщений: 5,788
|
Все ясно.. Тогда свой вариант пока оставлю как есть.
Но задача, вообще, заинтересовала ) Хотя бы потому, что раньше с таким не сталкивался. А что-то "более интересное" (и не очень) у меня по другим предметам ) Поэтому, когда захочется передохнуть, буду думать над этой задачей. И вот что непонятно: функция должна возвращать указатель на чар, но как тогда можно организовать память в виде единичных блоков с указателями на следующий? Вот никак не придумать, как избавиться от изначально заданного количества блоков. Вдруг юзер захочет выделить память под массив из 10 мегабайт char'ов.. В моем варианте, например, можно выделить только 1000 (ну или сколько укажешь). Мне кажется, или без этого ограничения никак не обойтись?
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем. ___________________________________ ___________________________________ _______ [=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль] |
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
своя функция | LeoN | PHP | 3 | 01.08.2009 21:54 |
malloc free Ошибка. | BeNN | Общие вопросы C/C++ | 19 | 09.07.2009 12:46 |
своя процедура | san72 | Общие вопросы Delphi | 6 | 26.05.2009 22:41 |
Проблемы с выделением динамической памяти malloc (recalloc) | slips | Общие вопросы C/C++ | 6 | 29.04.2009 19:27 |
Своя ОС | koljsch | Общие вопросы C/C++ | 5 | 22.03.2009 09:38 |