Перейти к содержанию
    

Размер структур, стек и куча

Пишем программу для нового прибора. Коллега создает вот такие структуры:

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. Мириться ли с тем, что коллега создает такие огромные структуры или надо сменить подход? Можно ли их располагать в функции или лучше глобально?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Заполнением стека константой перед запуском программы и проверкой, что наверху стека осталось какое-то количество ячеек с этой незатертой константой. Работает не всегда, но чаще всего работает.

2) Достаточный.

4) Да, memcpy. Нет, куча не используется. А зачем она могла бы при этом понадобиться?

5) Если нужна именно такая структура, то что вы тут сможете поменять?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

при вызове Си-шной функции все параметры, которые получает и возвращает функция, передаются через стек.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4) Да, memcpy. Нет, куча не используется. А зачем она могла бы при этом понадобиться?

 

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

 

5) Если нужна именно такая структура, то что вы тут сможете поменять?

 

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

 

А про размер - ну просто из опыта работы. Какой делали максимальным на приборе с МК такого класса и 32-64 МБ ОЗУ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А про размер - ну просто из опыта работы. Какой делали максимальным на приборе с МК такого класса и 32-64 МБ ОЗУ

 

А что у вас за прибор?

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

А все такие структуры сносятся в медленную внешнюю RAM в heap.

 

Имея такие ресурсы как у вас всегда применяют RTOS. А у развитых RTOS всегда есть механизмы наблюдения за стеком.

Причем в реальном времени.

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

Только когда речь шла о слишком замороченном стороннем софте например задачах клиентских сессий со встроенным WEB сервером стек увеличивал до 10 кб.

 

А коллегу вашего надо переучивать. Факт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Как вы контролируете переполнение стека?

2. Какой размер считаете оптимальным?

3. В какой памяти его лучше располагать?

4. Как реально происходит приравнивание структур? Это спрятанное от глаз memcpy? И используется ли при этом динамическое выделение памяти?

5. Мириться ли с тем, что коллега создает такие огромные структуры или надо сменить подход? Можно ли их располагать в функции или лучше глобально?

5. Коллеге за такое в embedded без внешней памяти, надо не просто по рукам бить, а ампутировать их. Лучше не данные, а коллегу расположить где-нить в вынь-программинге.

2. Оптимальных размеров стека нет, есть необходимые.

1. Контроль - заполнением шаблоном.

3. Лучше внутренней, особенно касаемо DSP с его огромными контекстами.

4. Согласно языка си: поэлементно. Распределение памяти и инициализация - вещи суть разные и почти несвязанные.

 

при вызове Си-шной функции все параметры, которые получает и возвращает функция, передаются через стек.

ложь.

 

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

В принципе можно и во внешней памяти стек располагать, даже на устройствах где есть жёсткий реалтайм.

Всё зависит от требуемого быстродействия данной задачи ОС и архитектуры CPU.

Если архитектура такова, что при возникновении прерывания контекст сохраняется на другом стеке (как на Cortex) или вообще не сохраняется (как в ARM TDMI), то стек некоей медленной задачи расположенный во внешней ОЗУ никак не затормозит ISR, но может затормозить переключение контекста данной медленной задачи ОС.

Как обстоит дело с сохранением контекста в Блэкфинах я не знаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

void make_TA(void){

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

 

у вас в стеке создается копия статической или глобальной структуры. Лучше использовать указатель

void make_TA(RTN* train){

    train->NoPt = ...;

 

или ссылку, если это С++

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще конструкция тип НовыйОбъект = Объект

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

PS это утверждение верно для С++ так как там структуры и классы одна сущность только с разными свойствами по умолчанию

 

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

 

PPS все функции работы с памятью memcpy malloc работают с кучей

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

PPS все функции работы с памятью memcpy malloc работают с кучей

 

А это не закон. Как в программе переопределено так и будет.

Скажем RTOS-ы сразу переопределяют эти функции.

А там у кого как, у кого куча, а у кого и много куч. Но все со своими оригинальными движками.

 

Кстати не додумал, но коллега действительно мог использовать стек именно для ускорения своей процедуры.

Либо вообще копипастить из среды моделирования один в один. Тогда это оправдано и придираться к нему нельзя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще конструкция тип НовыйОбъект = Объект

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

Не обязательно.

Если TRAIN - имеет тип RTN и перегружен оператор присваивания:

RTN & RTN::operator =(RTN &);

то (имхо) компилятор сделает вызов конструктора по умолчанию RTN::RTN(), а затем для созданного объекта вызовет этот перегруженный оператор присваивания: train(TRAIN)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не обязательно.

Если TRAIN - имеет тип RTN и перегружен оператор присваивания:

RTN & RTN::operator =(RTN &);

то (имхо) компилятор сделает вызов конструктора по умолчанию RTN::RTN(), а затем для созданного объекта вызовет этот перегруженный оператор присваивания: train(TRAIN)

 

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

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

Имея такие ресурсы как у вас всегда применяют RTOS. А у развитых RTOS всегда есть механизмы наблюдения за стеком.

...

 

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

 

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

 

...

Кстати не додумал, но коллега действительно мог использовать стек именно для ускорения своей процедуры.

Либо вообще копипастить из среды моделирования один в один. Тогда это оправдано и придираться к нему нельзя.

 

Не думаю, что для ускорения.

Пишет под WIN32, потом передает мне те части, которые платформо-независимы

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

у вас в стеке создается копия статической или глобальной структуры. Лучше использовать указатель
Кому лучше? Если там создается копия - наверное программисту нужна именно копия, он хочет ее менять, а содержимое оригинала потом потребуется в другом месте. А если можно работать с содержимым оригинальной струкьтуры, то и в этом случае указатель не нужен - можно работать прямо с самой структурой.

PPS все функции работы с памятью memcpy malloc работают с кучей
Каким местом memcpy связан с кучей?

Вы правильно сказали - используя конструктор,
Судя по "typedef struct" там голый Си, без плюсов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не думаю, что для ускорения.

Пишет под WIN32, потом передает мне те части, которые платформо-независимы

 

Ну так бы сразу и сказали.

А то вводите публику в заблуждение.

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

 

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

 

Просто портировать лень, да?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Судя по "typedef struct" там голый Си, без плюсов.

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

 

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

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

Именно так, согласен. Я сразу и написал, что это виндузятный подход, а не ембеддед.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...