|
0 / 0 / 0
Регистрация: 13.03.2015
Сообщений: 52
|
|
Зачем в Си нужно динамическое выделение памяти?25.07.2017, 21:15. Показов 12613. Ответов 31
Метки нет (Все метки)
Зачем в Си может потребоваться динамическое выделение памяти, если программа пишется для MCU ?
Иные товарищи говорят "что бы оптимальнее использовать память". Но это общее "за всё хорошее, против всего плохого". Давайте посмотрим, какие преимущества у динамического массива перед статическим. Ведь говоря о динамическом распределении памяти мы говорим именно о динамическом массиве, иначе какой толк - динамически выделить память под одну переменную и хранить на нее ссылку? Динамический массив может расширяться и сжиматься, а статический - нет. И, типа, если у нас мало неких объектов (точнее их предтечей - структурных переменных), то мы можем использовать мало памяти, если много - то сможем расширить массив. И если 90% времени наш массив занимает 10% памяти контролера, а 10% времени - 90% памяти, то в среднем массив будет занимать 18% памяти. Круто? Но смотрите. Если массив объектов у нас - один-единственный, а все остальные переменные - статические, то они или влезут в оставшиеся 10% физической памяти при пиковой нагрузке или не влезут. И если не влезут - беда-беда. А если влезут, то какая разница, заняты ли оставшиеся 90% памяти 10% времени или 100% времени? Если у нас массивов объектов два (и более), то динамические массивы могу дать выигрыш, если сумма максимальных размеров массивов больше 100% памяти MCU, но средняя сумма размеров массивов никогда не превысит 100% (и чем больше эта разница, тем эффективней использовать динамическое распределение памяти). Т.е. если данные о неких сущностях занимают, скажем, 60% памяти и при этом как-бы "перетекают" из массива в массив. Может ли кто-нибудь предложить красивый кейс/задачу в которой данные ведут себя подобным образом? P.S. Да, динамические массивы могут быть эффективны в случае наличия чего-то вроде файла подкачки (90% времени используем оперативную память, 10% - расширяемся в файл подкачки и теряем в скорости). Но! 1. В качестве вместилища файла подкачки флеш-память (а мы подразумеваем ее, говоря об MCU) не очень подходит. Постоянные перезаписи, знаете ли... 2. Говоря об MCU мы зачастую понимаем около-реалтаймовские задачи. А там вот-это-вот-всё "память кончилась, раскручиваю блины, ща-ща-ща, еще чуть-чуть", знаете ли...
0
|
|
| 25.07.2017, 21:15 | |
|
Ответы с готовыми решениями:
31
Нужно сделать динамическое выделение памяти
Нужно переделать код под динамическое выделение памяти |
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,864
|
|
| 26.07.2017, 02:37 | |
|
Я ж говорю - не парьтесь, когда вам понадобится динамическое выделение - вы почувствуете :-), а до того оно всё равно будет казаться неестественным.
Кстати, пример //Mt хорош. Пакеты разного размера, приходят себе потихоньку, потом уходят. Добавим сюда уход пакетов не в том порядке, в котором пришли (ну там, QoS, или порт для каких-то пакетов занят, или ещё что) - и получаем задачку, в которой динамическое выделение практически неизбежно. Правда, именно для этой задачки я бы использовал не malloc, а свой велосипед специально разработанный аллокатор.
0
|
|
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 382
|
||
| 26.07.2017, 02:50 | ||
|
Чето вы, ребята, ваапще не в ту степь ушли. Начали за здравие, за микроконтроллеры, а ушли в четрт знает вкуда.3дэМакс, рендерить... на микроконтроллере.. ну даёте. Вот в чем беда "неэмбеддеров", так в том, что они не понимают из чего состоит то, на чем они работают.
А теперь из той же функции напишем malloc(200) - как думаете, в какой области будет выделен адрес? И в виде чего он будет выделен? А где будет храниться переменная указателя, содержащая адрес выделенного массива? Вообще, почему вы думаете, что память должна обязательно быть загружена на 100% Да ну. При около 100% загрузке вы рискуете получить отказ выделения или "пробой" стека. Стек во многих микроконтроллерах хранится в ОЗУ. И еще. Допустим, у микроконтроллера 32 кБ ОЗУ, используется не больше 15 кБ и не будет больше, но зато у него 100 ножек и все заняты под завязку. Это неэффективное использование памяти? Прикажете ее выжечь? Ладно, есть микроконтроллер с 16 кБ ОЗУ но на 64 ножки - не хватает ножек. И чето вы забываете, что Си никоим образом не отслеживает границы массивов. Особенно когда они выделены с помощью указателя. Вам что, слово "указатель" ни о чем не говорит разве? Если вы пытаетесь провести параллели между PC и MCU, то нивкакую не получится - это совершенно разные системы, с разной организацией памяти и остального. Чето эти ваши категоричные рассуждения о видах памяти напоминают рассуждения гаражного мастера дяди Васи о вкусе черной и красной икры. Не попробовав на деле, вы все равно не поймете, как и для чего это работает. Вобщем, какая-то категоричная тема, но пустая совершенно. Ваще ниачом, как у нас выражаются. PS. Аа, я понял. Ясно. Это - вот что бывает, когда "неэмбеддеры" приходят в среду "эмбедда". Тогда у них и появляются файлы подкачки на флеше, да и про внешнюю ОЗУ они ниче не слышали, да и про карту памяти (распределение адресов) тоже.
0
|
||
|
0 / 0 / 0
Регистрация: 24.08.2009
Сообщений: 3
|
|
| 26.07.2017, 02:57 | |
|
Связанные списки например.. Бывает очень удобно для хранения каких либо событий.
0
|
|
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,864
|
|
| 26.07.2017, 03:08 | |
|
Кстати, вспомнил эмбеддерскую хрень, в которой есть не то что динамическое выделение памяти - garbage collector. NodeMCU.
0
|
|
|
1 / 1 / 0
Регистрация: 05.10.2017
Сообщений: 2,048
|
|
| 26.07.2017, 08:03 | |
|
В одном из недавних проектов на STM32F4 в SDROM было 64МБайта. И то, без динамического выделения не получалось статически сразу дать нужные объемы, только под критичные вещи, типа видеобуфера для экрана, для GUI и прочее. Память(куча) RTOS, TCP/IP, и прочее крутилось в в внешней SDROM, менеджер памяти использовал от FriiRTOS. Сильно упрощало жизнь.
0
|
|
|
0 / 0 / 0
Регистрация: 20.06.2010
Сообщений: 454
|
|||||||
| 26.07.2017, 12:09 | |||||||
пример
0
|
|||||||
|
0 / 0 / 0
Регистрация: 24.08.2009
Сообщений: 3
|
||
| 26.07.2017, 14:33 | ||
0
|
||
|
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
|
||
| 26.07.2017, 15:27 | ||
0
|
||
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 1,864
|
|
| 26.07.2017, 15:30 | |
|
Это товарищ не знает разницы между автоматическими и статическими переменными. Явно говорит об автоматических.
А что буфер может понадобиться после выхода из функции - ему в голову не пришло. Ничего страшного, со временем разберётся.
0
|
|
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 382
|
|||||||||||
| 26.07.2017, 15:59 | |||||||||||
|
Эхехех.... Да этот "товарищь" со своим категоричным первым постом темы, претендующем по меньшей мере на "How to..." вообще чето заблудился в трех березах. Всё смешал - и файлы подкачки, которых в MCU не существует в том виде, которые он представляет, и флеш, и массивы. А про указатели он вообще видимо не слыхивал. Да и с представлением об организации памяти вообще - тож проблема. Зато суждения категоричные.. ну...
Статический массив, по определению языка Си, никуда не растворится при выходе из функции, потому что он объявлен квалификатором static и размещается в секции ОЗУ, определенной для таких массивов. В отличие от массивов, время жизни которых ограничено рамками функции. Посмотрите наглядно: первая функция, в которой объявлены: обычным образом массив из 8 однобайтных элементов (автоматические), массив из 8 элементов static, и указатель, полученный динамически через malloc на 16 элементов
Видны наши 8 автоматических элементов в стеке и указатель, полученный от malloc. <Изображение удалено> потом вызывается вторая функция из первой: и аналогично то же самое с индексом 2.
<Изображение удалено> А где же наши элементы, полученные по malloc??? и где массивы static??? Смотрим, на какие адреса указывают указатели в области стеков. Видим, что они указывают уже где-то в начале адресов ROM (начинаются с 0х2000 0000) и бежим туда: вот они! первый и второй массив: и там с удивлением (!) обнаруживаем наши static-массивы, которые мы выделяли в функциях: <Изображение удалено> Так же, на последнем скрине, анализируя занимаемые адреса malloc-выделений, обнаруживаем "дырку" в 8 байт. Догадайтесь, что это за байда, и почему она всегда появляется между malloc-выделениями? Домашнее задание топикстартеру, разобраться, раз уж он претендует на "How to..."
0
|
|||||||||||
|
0 / 0 / 0
Регистрация: 13.03.2015
Сообщений: 52
|
||
| 26.07.2017, 16:55 | ||
- Автоматический буфер легко удаляется из стека по завершении функции. - Автоматический буфер нельзя передать, а вот динамический... - Хорошо. Статический (или глобальный) буфер доступен любой функции. - Глобальный буфер нельзя удалить, а вот динамический... - Автоматический можно удалить - А вот динамический... - Статический будет доступен - А вот динамический... - Не хватает памяти - возьмите MCU подороже. - Растратчик! Лучше сделаю динамические буферы. - А если они одновременно разрастуться до размеров физ.памяти? - Далась вам эта память! Куплю MCU подороже! - Может лучше - статический массив и MCU подороже? - Растратчик! Только malloc, только хардкор! - А если физ.памяти не хватит? - Куплю подороже, какие проблемы? Судя по топику: 1. Динамический буфер в единственном числе легко заменяется статическим буфером такого же размера. 2. Динамический буфер в количестве "два и более" - отличный способ снизить цену аппаратной части системы за счет снижения надежности софтовой части. Об этом следует помнить!
0
|
||
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 382
|
||||||||
| 26.07.2017, 17:04 | ||||||||
|
Апять-двацатьпять. В Си нет понятия "динамического буфера". Буфер, выделяемый с помощью аллокатора - это всего лишь У-К-А-З-А-Т-Е-Л-Ь, указатель, 4-хбайтовая переменная (в 32-битной системе), содержащая АДРЕС первого элемента выделенного буфера (массива). А указатель можно и ручками выделить, в любом месте. И даже void*. По соглашениям, размер void* = 1 байт.
Черт, ему уже и "веселые картинки" нарисовал для прозрения, а он всё еще с менторством "следует помнить". Фееричный чел, хаха :) Ирсений, оставьте этот ваш менторский тон, а то недайбог кто прочтет, либо так же заблудится, либо смеяться будет.
С квалификатором static - НЕ доступен любым функциям кроме родительской. Но когда она будет вызвана, буфер заново не будет создаваться, и в нем содержимое осталось от предыдущего вызова функции, в целости и сохранности.
uint8_t *buf3 = ptr + 32; int32_t *buf4 = ptr + 50; Нннна-тебе, пользуйтесь вместо бывшего uint32_t globbuf[1000]. Но помните, обращение globbuf[10] = 50 испортит ваши новые буфера. Потому что имя буфера в системе осталось.
Ирсений писал(а):
Ирсений, вы уж определитесь, в чем вы "варитесь" - в эмбедде или в писюках? Потому что в эмбедде никто не будет выбирать МК впритык тютелька-в-тютельку. В большинстве случаев. Потому что: а) прошивки могут обновляться в рамках сопровождения и поддержки устройства, добавляя или улучшая функционал. Нехватило памяти? перепаивать никто не станет. б) прошивки могут исправляться на местах, когда обнаружен косяк не по вине программиста, а из-за недоработки составителей техзадания, а то и просто слегка другие условия, такое бывает. Прагриннист ругается матом, но делает, потому что "косяки заказчиков - за их счет". в) программист сам может накосячить, типа "ах чорт, сигнал на входе АЦП шумит же сильно, надо было вместо скользящего среднего фильтр Калмана ставить" г) железо подбирается не только по объемам ОЗУ, но и по аппаратному функционалу, по доступности, по наличию вообще таких моделей. д) двухкратная разница в объеме ОЗУ = 10-15% разницы в цене при прочих равных условиях е) глубина "просадки" стека вниз по адресам при использовании сторонних библиотек заранее неизвестна и не поддается точному до байта описанию. Следствие - всегда, запомните, ВСЕГДА есть довольно большой запас ОЗУ, рассчитанный на потребление стека и не используемый постоянно. На тяжелых сторонних либах глубина просадки стека может быть очень и очень значительной. ж) куча (heap), из которой распределяется память для этих ваших динамических буферов, не может быть равна размеру ОЗУ целиком. Иначе у вас всё перехлестнется. Именно по этим соображениям, использования ОЗУ на 99%, как вы хотите - не бывает по определению. 99% - это один миг до сбоя и -> Ирсений писал(а):
PS. График использования ОЗУ МК в обобщенных среднестатистических применениях: https://www.cyberforum.ru/savedimages/2017/07/26/wghpxnjsmasajw9rtyz.png
0
|
||||||||
| 26.07.2017, 17:04 | |
|
Нужно переделать код под динамическое выделение памяти Нужно немного переделать программу: использовать функции и динамическое выделение памяти
Распределение памяти. Динамическое выделение памяти Динамическое выделение памяти Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства.
Родственных связей существует 8 ступеней, такие как:
p - отец
P - мать
q - муж
Q - жена
b - брат
B - сестра
s - сын
S - дочь
|
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире.
Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
|
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С.
Задача:
Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
|
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
|
|
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
|
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701
Купил два термопринтера QR701.
На сэлф-тесте написано:
Language: PC936 (GB18030).
Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
|
Создание формы заимствованного документа
Maks 03.08.2026
Задача:
Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также
табличная часть со следующими реквизитами:
- Расчетный счет покупателя. . .
|
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача:
В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
|