|
ООП. Классы и динамические объекты, Подробности управления «кучей» |
|
|
|
Aug 17 2016, 11:33
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Serhiy_UA @ Aug 17 2016, 11:59)  4. Что можно почитать на эту тему по-подробней? Хорошие вопросы... Правда немного из серии "почему солнце светит?"  Функции управления кучей (malloc/free) и более модные new/delete реализованы в библиотеках. Они пользуются памятью, которые просят у ОС, если такая есть вообще. В Ц++ new/delete можно довольно легко переопределить и сделать свои аллокаторы. Память выделяемая new/malloc всегда непрерывная (с точки зрения ее пользователя). Читать начиная со Страуструпа.. Ну, или Кернигана с Ричи.
|
|
|
|
|
Aug 17 2016, 12:06
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(CrimsonPig @ Aug 17 2016, 14:33)  Читать начиная со Страуструпа.. Ну, или Кернигана с Ричи. Это занятие ни к чему хорошему не приведет. Кучи слишком сложная тема чтобы пользоваться старыми книгами. Первое что надо знать - это то что кучи делают все. И ОС, и компилятор, и сами прикладные программы их могут переопределять. Т.е. в одной среде разработки вы можете иметь выбор нескольких движков куч. Например в RAD Studio под Windows есть старый движок кучи, новый движок и движок который они наследуют из API Windows. Для встраиваемых систем еще все хуже и запутанней. Во первых, стандартное управление кучей есть в библиотеках компилятора. Но даже так там есть механизм подстройки когда самые низкоуровневые функции движка кучи программист должен подстроить сам. Во всех RTOS тоже есть свои механизмы кучи поскольку они не надеются на штатную подстройку компилятора. Во FreeRTOS аж три движка кучи на выбор. Для RTOS куча является очень критичным моментом поскольку надо обеспечить фиксированное время выполнения ее функций и безопасный доступ при многозадачности, часто еще и таймаут доступа делают. Поэтому стандартные библиотечные кучи не используют, а перенаправляют new/delete на свои функции. Однако при старте программы движок RTOS еще не работает, поэтому конструкторы объектов могут напороться еще на библиотечные функции. Короче в этой теме кругом грабли. Читать надо мануал на конкретный компилятор и ОС. Классики не помогут.
|
|
|
|
|
Aug 30 2016, 05:12
|
Знающий
   
Группа: Свой
Сообщений: 721
Регистрация: 23-10-08
Из: next to Odessa
Пользователь №: 41 112

|
Спасибо за разъяснения. Пока еще не все понятно, но мнение мое по этому вопросу складывается такое. Память под «кучу» упорядочивается и представляется, как бы в виде большой кассеты с группами коробочек разных величин. При создании объекта, ему выделяется нужная по размеру коробочка, а если они закончились, то большая из ближайшей группы. Если коробочек уже не хватает, то на основе статистики о требуемых размерах памяти создают следующую кассету. Для кассеты ведется текущий реестр учета свободных и занятых коробок, по которому и выделяется указатель на свободную память. То есть, кучи, и тем более «мало-кучи» в нашем понимании, как токовой нет, а все как бы строго упорядочено и физическая память под один динамический объект все же непрерывна, а не размазана с разрывами по её разным областям. Поправьте, если понял не так…
|
|
|
|
|
Aug 30 2016, 05:27
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Serhiy_UA @ Aug 30 2016, 08:12)  Память под «кучу» упорядочивается и представляется, как бы в виде большой кассеты с группами коробочек разных величин. Это всего лишь одна из очень многих стратегий. На начальном этапе вы можете об этом не задумываться. Вы просто можете пока считать, что есть некая "куча" из которой вам выделят непрерывный кусок запрошенного вами размера. Или не выделят, если непрерывного куска запрошенного размера в данный момент в куче нет. QUOTE (Serhiy_UA @ Aug 30 2016, 08:12)  и физическая память под один динамический объект все же непрерывна, а не размазана с разрывами по её разным областям Это вам сказали в самом первом ответе. Как же может быть иначе? Система же не знает, что вы там хотите разместить. Но вы можете некоторые данные своего объекта хранить отдельно, в дополнительно запрашиваемой памяти. Запрашивать ее можно в конструкторе, а освобождать - в деструкторе.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 30 2016, 10:14
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Serhiy_UA @ Aug 30 2016, 11:03)  А какие еще есть стратегии управления кучей? Где об этом почитать? ТутQUOTE (Serhiy_UA @ Aug 30 2016, 11:03)  А как ее заполняют вновь, только ли объектами не большими по размеру от предыдущего? Зависит от реализации. Вменяемому менеджеру памяти ничего не мешает объединить освободившийся участок с соседними свободными.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 30 2016, 10:16
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Сергей Борщ @ Aug 30 2016, 11:27)  Это вам сказали в самом первом ответе. Как же может быть иначе? Система же не знает, что вы там хотите разместить. Но вы можете некоторые данные своего объекта хранить отдельно, в дополнительно запрашиваемой памяти. Запрашивать ее можно в конструкторе, а освобождать - в деструкторе. В общем случае - это не так. Никто не мешает системе, в распоряжении которой есть MMU, сделать маппирование одного сплошного диапазона логических адресов (блока памяти выделяемого пользовательскому ПО) на несколько несмежных диапазонов физических адресов. А вот делает-ли такое какая-то конкретная ОС или нет - не знаю. Цитата(Сергей Борщ @ Aug 30 2016, 16:14)  Зависит от реализации. Вменяемому менеджеру памяти ничего не мешает объединить освободившийся участок с соседними свободными. Вменяемый может даже несмежные физические блоки объединить. Воспользовавшись услугами MMU.
|
|
|
|
|
Aug 30 2016, 11:08
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AlexandrY @ Aug 30 2016, 16:51)  Думаю что штатные менеджеры, скажем на PC, не привлекают MMU. Это слишком затратно по времени. Ну - не очень затратно. Например: можно реализовать это в обработчике void * недостаточно_памяти(ulong требуемый_размер)Такой обработчик может собрать имеющиеся разрозненные свободные блоки и в специально выделенном диапазоне лог. адресов построить карту перемаппирования, сохранить себе полученный лог.адрес и вернуть его. В delete надо будет конечно сделать проверку на предмет освобождения такого блока. В некоторых случаях думаю важнее всё-таки получить память, пусть и чуть медленнее. Но медленее будет идти работа только с этими блоками, с обычными блоками - примерно так же. Не говорю что это где-то так реализовано. Просто это возможно.
|
|
|
|
|
Oct 3 2016, 17:18
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(AlexandrY @ Aug 17 2016, 15:06)  Во FreeRTOS аж три движка кучи на выбор. ... Читать надо мануал на конкретный компилятор и ОС. Классики не помогут. Точнее 5. )) heap_1 - the very simplest, does not permit memory to be freed • heap_2 - permits memory to be freed, but not does coalescence adjacent free blocks. • heap_3 - simply wraps the standard malloc() and free() for thread safety • heap_4 - coalescences adjacent free blocks to avoid fragmentation. Includes absolute address placement option • heap_5 - as per heap_4, with the ability to span the heap across multiple non-adjacent memory areas
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|