реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Размер структур, стек и куча, Максимальный размер структур, их копирование, стек и куча
kolobochishe
сообщение Dec 22 2015, 16:07
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 14-04-10
Из: Россия, г.Челябинск
Пользователь №: 56 634



Пишем программу для нового прибора. Коллега создает вот такие структуры:
Код
typedef struct    {
    REC_HEADER Header;
    WORD NoPT;
    WORD NoPL;
    WORD NoAD;
    WORD StationID;
    WORD ModelID;
    WORD ManufactID;
    char Ident[9];
    char Descript[41];
    WORD StatTime;
    WORD NoFR;
    WORD NoRT;
    WORD NoBL;
    BYTE NoKY;
    BYTE NoPR;
    BYTE UnitsCal[7];
    float Units0dB[7];
    char KeyId[3][5];
    char KeyDescr[3][41];
    BYTE KeyGrade[3];
    float Factor[3];
    BYTE KeyTStamp[3][8];
    float KeyNom[3];
    float RPM[3];
    char KeyNotes[3][241];
    char PrId[12][9];
    char PrDescr[12][41];
    char Units[12][7];
    BYTE PrGrade[12];
    BYTE PrTStamp[12][8];
    float PrNom[12];
    float PrVal[12];
    char PrNotes[12][241];
                } RTN;


и вот в таком вот месте программа "виснет"
Код
void make_TA(void)
{
    BYTE    get_status(BYTE);

    RTN train=TRAIN; // ТУТ ЗАВИСАЕТ


Увеличил размер стека и все заработало. Был 3кБ сделал 10кБ. Правда, из SCRTACHPAD пришлось перенести в L1 из-за размера.
Контроллер Blackfin BF-548.

Теперь вопросы:
1. Как вы контролируете переполнение стека?
2. Какой размер считаете оптимальным?
3. В какой памяти его лучше располагать?
4. Как реально происходит приравнивание структур? Это спрятанное от глаз memcpy? И используется ли при этом динамическое выделение памяти?
5. Мириться ли с тем, что коллега создает такие огромные структуры или надо сменить подход? Можно ли их располагать в функции или лучше глобально?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 22 2015, 16:39
Сообщение #2


Гуру
******

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



1) Заполнением стека константой перед запуском программы и проверкой, что наверху стека осталось какое-то количество ячеек с этой незатертой константой. Работает не всегда, но чаще всего работает.
2) Достаточный.
4) Да, memcpy. Нет, куча не используется. А зачем она могла бы при этом понадобиться?
5) Если нужна именно такая структура, то что вы тут сможете поменять?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
quarter
сообщение Dec 22 2015, 16:55
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 66
Регистрация: 17-12-15
Пользователь №: 89 731



при вызове Си-шной функции все параметры, которые получает и возвращает функция, передаются через стек.
если не побоитесь, то можно работать с указателями на эти структуры, тогда лишнего копирования можно избежать.
Go to the top of the page
 
+Quote Post
kolobochishe
сообщение Dec 22 2015, 17:08
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 14-04-10
Из: Россия, г.Челябинск
Пользователь №: 56 634



Цитата(Сергей Борщ @ Dec 22 2015, 22:39) *
4) Да, memcpy. Нет, куча не используется. А зачем она могла бы при этом понадобиться?


Не знаю. Подумал, может создается копия, а потом копируется для случая memcpy с перекрывающимися областями памяти.

Цитата(Сергей Борщ @ Dec 22 2015, 22:39) *
5) Если нужна именно такая структура, то что вы тут сможете поменять?


Ну как-то сделать свою часть программы такой, чтобы не было таких огромных локальных переменных. Пусть они будут, но не локальными переменными же. Если подойти к этому с размахом то там и мегабайтные маассивы начнут локально объявлять. Так никакого стека не хватит.

А про размер - ну просто из опыта работы. Какой делали максимальным на приборе с МК такого класса и 32-64 МБ ОЗУ
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Dec 22 2015, 21:03
Сообщение #5


Ally
******

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



Цитата(kolobochishe @ Dec 22 2015, 19:08) *
А про размер - ну просто из опыта работы. Какой делали максимальным на приборе с МК такого класса и 32-64 МБ ОЗУ


А что у вас за прибор?
Стек он в дивайсах с реальным временем на вес золота. Ибо организуется в быстрой внутренней RAM, даже TCM RAM.
А все такие структуры сносятся в медленную внешнюю RAM в heap.

Имея такие ресурсы как у вас всегда применяют RTOS. А у развитых RTOS всегда есть механизмы наблюдения за стеком.
Причем в реальном времени.
У меня даже на платах с 128 МБ памяти стек задач никогда не превышал 5 Кб. Если нужно больше, то это уже какие-то проблемы с софтом.
Только когда речь шла о слишком замороченном стороннем софте например задачах клиентских сессий со встроенным WEB сервером стек увеличивал до 10 кб.

А коллегу вашего надо переучивать. Факт.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Dec 23 2015, 05:45
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(kolobochishe @ Dec 22 2015, 22:07) *
1. Как вы контролируете переполнение стека?
2. Какой размер считаете оптимальным?
3. В какой памяти его лучше располагать?
4. Как реально происходит приравнивание структур? Это спрятанное от глаз memcpy? И используется ли при этом динамическое выделение памяти?
5. Мириться ли с тем, что коллега создает такие огромные структуры или надо сменить подход? Можно ли их располагать в функции или лучше глобально?

5. Коллеге за такое в embedded без внешней памяти, надо не просто по рукам бить, а ампутировать их. Лучше не данные, а коллегу расположить где-нить в вынь-программинге.
2. Оптимальных размеров стека нет, есть необходимые.
1. Контроль - заполнением шаблоном.
3. Лучше внутренней, особенно касаемо DSP с его огромными контекстами.
4. Согласно языка си: поэлементно. Распределение памяти и инициализация - вещи суть разные и почти несвязанные.

Цитата(quarter @ Dec 22 2015, 22:55) *
при вызове Си-шной функции все параметры, которые получает и возвращает функция, передаются через стек.

ложь.

Цитата(AlexandrY @ Dec 23 2015, 03:03) *
Стек он в дивайсах с реальным временем на вес золота. Ибо организуется в быстрой внутренней RAM, даже TCM RAM.

В принципе можно и во внешней памяти стек располагать, даже на устройствах где есть жёсткий реалтайм.
Всё зависит от требуемого быстродействия данной задачи ОС и архитектуры CPU.
Если архитектура такова, что при возникновении прерывания контекст сохраняется на другом стеке (как на Cortex) или вообще не сохраняется (как в ARM TDMI), то стек некоей медленной задачи расположенный во внешней ОЗУ никак не затормозит ISR, но может затормозить переключение контекста данной медленной задачи ОС.
Как обстоит дело с сохранением контекста в Блэкфинах я не знаю.
Go to the top of the page
 
+Quote Post
psL
сообщение Dec 23 2015, 06:44
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



Цитата(kolobochishe @ Dec 22 2015, 19:07) *
Код
void make_TA(void){

    RTN train=TRAIN; // ТУТ ЗАВИСАЕТ


у вас в стеке создается копия статической или глобальной структуры. Лучше использовать указатель
Код
void make_TA(RTN* train){

    train->NoPt = ...;


или ссылку, если это С++
Go to the top of the page
 
+Quote Post
SlavaV
сообщение Dec 23 2015, 06:52
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 13-06-06
Из: г.Улан-Удэ
Пользователь №: 18 024



Вообще конструкция тип НовыйОбъект = Объект
говорит создать временный объект типа "тип" (вот он видимо и создаётся на стеке) и скопировать его в НовыйОбъект (именно скопировать, если не перегружен оператор= происходит почленное копирование)
PS это утверждение верно для С++ так как там структуры и классы одна сущность только с разными свойствами по умолчанию

Другого использование стека в приведённом коде я не вижу

PPS все функции работы с памятью memcpy malloc работают с кучей
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Dec 23 2015, 06:58
Сообщение #9


Ally
******

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



Цитата(SlavaV @ Dec 23 2015, 08:52) *
PPS все функции работы с памятью memcpy malloc работают с кучей


А это не закон. Как в программе переопределено так и будет.
Скажем RTOS-ы сразу переопределяют эти функции.
А там у кого как, у кого куча, а у кого и много куч. Но все со своими оригинальными движками.

Кстати не додумал, но коллега действительно мог использовать стек именно для ускорения своей процедуры.
Либо вообще копипастить из среды моделирования один в один. Тогда это оправдано и придираться к нему нельзя.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Dec 23 2015, 08:14
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(SlavaV @ Dec 23 2015, 12:52) *
Вообще конструкция тип НовыйОбъект = Объект
говорит создать временный объект типа "тип" (вот он видимо и создаётся на стеке) и скопировать его в НовыйОбъект (именно скопировать, если не перегружен оператор= происходит почленное копирование)

Не обязательно.
Если TRAIN - имеет тип RTN и перегружен оператор присваивания:
RTN & RTN::operator =(RTN &);
то (имхо) компилятор сделает вызов конструктора по умолчанию RTN::RTN(), а затем для созданного объекта вызовет этот перегруженный оператор присваивания: train(TRAIN)
Go to the top of the page
 
+Quote Post
SlavaV
сообщение Dec 23 2015, 08:29
Сообщение #11


Частый гость
**

Группа: Свой
Сообщений: 100
Регистрация: 13-06-06
Из: г.Улан-Удэ
Пользователь №: 18 024



Цитата(jcxz @ Dec 23 2015, 17:14) *
Не обязательно.
Если TRAIN - имеет тип RTN и перегружен оператор присваивания:
RTN & RTN::operator =(RTN &);
то (имхо) компилятор сделает вызов конструктора по умолчанию RTN::RTN(), а затем для созданного объекта вызовет этот перегруженный оператор присваивания: train(TRAIN)


вот этот объект и создаётся на стеке (вернее в автоматической памяти, а она обычно на стеке)

здесь можно обойтись без стека (автоматической памяти) Вы правильно сказали используя конструктор, но в коде нет этого, да и вопрос был почему не работает, а не как сделать чтоб работало

Go to the top of the page
 
+Quote Post
kolobochishe
сообщение Dec 23 2015, 09:08
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 240
Регистрация: 14-04-10
Из: Россия, г.Челябинск
Пользователь №: 56 634



Цитата(AlexandrY @ Dec 23 2015, 02:03) *
...
Имея такие ресурсы как у вас всегда применяют RTOS. А у развитых RTOS всегда есть механизмы наблюдения за стеком.
...


Решили не использовать, т.к. задача одна, а библиотека драйверов наличия ОС не требует.

Забыл упомянуть - пишем на СИ без плюсов.

Цитата(AlexandrY @ Dec 23 2015, 11:58) *
...
Кстати не додумал, но коллега действительно мог использовать стек именно для ускорения своей процедуры.
Либо вообще копипастить из среды моделирования один в один. Тогда это оправдано и придираться к нему нельзя.


Не думаю, что для ускорения.
Пишет под WIN32, потом передает мне те части, которые платформо-независимы
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 23 2015, 09:10
Сообщение #13


Гуру
******

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



Цитата(psL @ Dec 23 2015, 09:44) *
у вас в стеке создается копия статической или глобальной структуры. Лучше использовать указатель
Кому лучше? Если там создается копия - наверное программисту нужна именно копия, он хочет ее менять, а содержимое оригинала потом потребуется в другом месте. А если можно работать с содержимым оригинальной струкьтуры, то и в этом случае указатель не нужен - можно работать прямо с самой структурой.
Цитата(SlavaV @ Dec 23 2015, 09:52) *
PPS все функции работы с памятью memcpy malloc работают с кучей
Каким местом memcpy связан с кучей?
Цитата(SlavaV @ Dec 23 2015, 11:29) *
Вы правильно сказали - используя конструктор,
Судя по "typedef struct" там голый Си, без плюсов.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Dec 23 2015, 09:21
Сообщение #14


Ally
******

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



Цитата(kolobochishe @ Dec 23 2015, 11:08) *
Не думаю, что для ускорения.
Пишет под WIN32, потом передает мне те части, которые платформо-независимы


Ну так бы сразу и сказали.
А то вводите публику в заблуждение.
В Win32 он может писать как ему вздумается, и ничего ему за это не будет.

Вы портируете эти куски, вы и отвечаете за стек.

Просто портировать лень, да?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Dec 23 2015, 09:27
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Сергей Борщ @ Dec 23 2015, 15:10) *
Судя по "typedef struct" там голый Си, без плюсов.

Никто не мешает использовать "typedef struct" под с++.

Цитата(AlexandrY @ Dec 23 2015, 15:21) *
В Win32 он может писать как ему вздумается, и ничего ему за это не будет.
Вы портируете эти куски, вы и отвечаете за стек.

Именно так, согласен. Я сразу и написал, что это виндузятный подход, а не ембеддед.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 18:35
Рейтинг@Mail.ru


Страница сгенерированна за 0.01997 секунд с 7
ELECTRONIX ©2004-2016