Проблема с кодом
- Войдите на сайт для отправки комментариев
Вс, 11/07/2021 - 13:11
Всем привет. Опыта в С++ у меня нет совсем. Не могу понять, что происходит не так в моем коде.
Цель - написать менеджер состояний. Регистрируем состояние и callback функцию для этого состояния. в loop, при каждой итерации вызываем tick(), который должен смотреть на текущее состояния и запускать callback, который ему соответсвует.
state.h
#ifndef _STATE_CPP_ #define _STATE_CPP_ enum SystemStates { INITIALIZE = 0, // инициализация при запуске INIT_FAILED = 1, // когда предполетная проверка провалилась READY = 2, // готовность к старту FLY = 3, // полет. Определяется по растущей высоте LANDING = 4, // снижение LANDED = 5 // произошла посадка определяется по неподвижности }; typedef void (*state_tick_clb)(); class StateManager { public: StateManager(); void register_state(int state, state_tick_clb clb); void set_state(int state); void tick(); private: int internal_states[3]; state_tick_clb clb[]; int states_count; int active_state; }; #endif
state.cpp
#include <Arduino.h> #include "state.h" StateManager::StateManager() { states_count = 0; } void StateManager::register_state(int state, state_tick_clb c) { internal_states[states_count] = state; clb[states_count] = c; Serial.print("Register state "); Serial.print(state); Serial.print(" postion "); Serial.println(states_count); states_count += 1; } void StateManager::set_state(int state) { Serial.print("states_count = "); Serial.println(states_count); for (int i=0; i < states_count; ++i) { Serial.print("Check state "); Serial.println(internal_states[i]); if (internal_states[i] == state) { active_state = internal_states[i]; Serial.print("SET STATE "); Serial.println(internal_states[i]); return; } } Serial.print("STATE NOT FOUND "); Serial.println(state); } void StateManager::tick() { Serial.print("TICK WITH STATE "); Serial.println(active_state); }
main.cpp
#include <Arduino.h> #include <state.h> StateManager sm; void state1() { Serial.println("state 1"); } void state2() { Serial.println("state 2"); } void state3() { Serial.println("state 3"); } void setup() { Serial.begin(9600); sm.register_state(INITIALIZE, &state1); sm.register_state(READY, &state2); } bool c1 = false; bool c2 = false; void loop() { sm.tick(); delay(1000); if (millis() > 5 * 1000 && !c1) { sm.set_state(READY); c1 = true; } if (millis() > 10 * 1000 && !c2) { sm.set_state(INITIALIZE); c2 = true; } }
Проблемы:Даже при первом вызове register_state, states_count почему-то не 0. В логе записи
Register state 0 postion 2294 Register state 2 postion 2295
Ну и дальше начинаются какие-то приколы, такое ощущение что в массив internal_state записывается мусор, но я не могу понять где я не прав. Полный лог:
Register state 0 postion 2294 Register state 2 postion 2295 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 states_count = 2296 Check state 0 Check state 0 Check state 0 Check state 2296 Check state 0 Check state 0 Check state 0 Check state 439 Check state 0 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 2573 Check state 0 Check state 0 Check state -1 Check state 10 Check state 10 Check state 650 Check state 2561 Check state 513 Check state 258 Check state -5632 Check state -9609 Check state -6194 Check state -1027 Check state -15390 Check state 21994 Check state -1554 Check state -25228 Check state 29563 Check state -25878 Check state -6227 Check state 27135 Check state -24610 Check state 31195 Check state -8517 Check state -358 Check state -6675 Check state 4349 Check state 3502 Check state -20554 Check state -17457 Check state -25758 Check state -24645 Check state -18179 Check state -4216 Check state -74 Check state -26773 Check state -8211 Check state -8449 Check state -129 Check state -20625 Check state -2594 Check state -10657 Check state -20558 Check state -2338 Check state 32729 Check state -1753 Check state -21562 Check state -24675 Check state -2097 Check state -3590 Check state -17508 Check state 26614 Check state -51 Check state -12739 Check state 32244 Check state 32641 Check state -2699 Check state -3981 Check state -26753 Check state 13749 Check state 11455 Check state 13726 Check state -4375 Check state 16055 Check state -513 Check state 15273 Check state -533 Check state -11524 Check state -4521 Check state -3587 Check state 16327 Check state 16054 Check state -24837 Check state -24846 Check state -8531 Check state -18035 Check state 10391 Check state -10241 Check state -5155 Check state -10291 Check state 13861 Check state -833 Check state 30693 Check state -11590 Check state -5192 Check state -906 Check state 12287 Check state -23649 Check state 28297 Check state 20433 Check state -5329 Check state 24183 Check state -1041 Check state 31690 Check state -4689 Check state 15193 Check state 15695 Check state 28069 Check state -16953 Check state -69 Check state -9 Check state 31739 Check state -4125 Check state 23757 Check state 14282 Check state -13844 Check state -1223 Check state -18571 Check state 10520 Check state -9 Check state -4197 Check state 32765 Check state -24597 Check state 24535 Check state -12435 Check state -459 Check state 32477 Check state -16386 Check state -6936 Check state -201 Check state -1353 Check state 12408 Check state -26113 Check state -3083 Check state -2050 Check state -25729 Check state -2012 Check state -173 Check state 27439 Check state -22027 Check state -6183 Check state 23486 Check state 31085 Check state -23813 Check state -2191 Check state 16127 Check state -9993 Check state -10562 Check state 15597 Check state -18562 Check state 30587 Check state 2139 Check state -1610 Check state -269 Check state -4935 Check state 3710 Check state 29918 Check state 31561 Check state 24562 Check state 28143 Check state -16666 Check state 17982 Check state -4129 Check state 21471 Check state -16463 Check state -7251 Check state -2253 Check state -22089 Check state 3321 Check state 13883 Check state -21513 Check state -16645 Check state -16985 Check state -30523 Check state 15231 Check state 28652 Check state 32254 Check state 14653 Check state -47 Check state 18189 Check state -24648 Check state -24581 Check state -3468 Check state -24833 Check state -28683 Check state -17243 Check state -5961 Check state -4594 Check state -8260 Check state 32763 Check state 27632 Check state -3012 Check state -17797 Check state -6219 Check state -28948 Check state 29674 Check state -1028 Check state 32435 Check state -10538 Check state -9 Check state 32486 Check state 9227 Check state 31900 Check state 23288 Check state 28670 Check state -3347 Check state -7538 Check state -29200 Check state -1060 Check state -11866 Check state -24755 Check state 11455 Check state -2689 Check state 29411 Check state -22022 Check state -16673 Check state -26634 Check state 19324 Check state -5129 Check state -147 Check state 7816 Check state -17549 Check state 31166 Check state -10369 Check state -18867 Check state 12975 Check state 23258 Check state -23178 Check state -323 Check state -18130 Check state -9356 Check state -2714 Check state -16782 Check state 2 SET STATE 2 TICK WITH STATE 2 states_count = 2296 Check state 0 SET STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0 TICK WITH STATE 0
Очень надеюсь, что вы поможете понять, что я сделал не так, у меня уже нет идей (
У тебя память под массив clb не выделена. Соответственно, когда ты в него пишешь, затираются следующие за ним переменные.
А вообще, в таком стиле под малопроизводительные МК не пишут.
Спасибо, попробовал убрать clb в самый низ и все стало ОК. Тогда надо либо выделять заранее, через new, либо делать realloc перед каждым добавлением?
Насчет стиля, я не очень понял что именно не так, то что не бьют на классы, или то что такую задачу решают просто переменной и switch?
Не делают стопок коллбеков.
Эм, а в чем разница? Все равно надо писать эти функции, все равно их запускать, пожертвовать немного памяти на то что бы хранить указатели на эти функции - что тут страшного?
Если это чисто стиллистически не верно, то тема холиварная, конечно
Статический анализ расхода ресурсов, отладка.
Не делают стопок коллбеков.
От если бы ты написал не делают динамических стопок коллбеков, то это было бы и правда и понятно. Смыслу их регистрировать... А статически - да сколько угодно.
И если хош действительно нумеровать состояния - так смыслу в internal_states? считай номер состояния индексом для clb. Но память под clb выдели.
И так не делают. Тупо лишние буквы.
Даже для "малопроизводительных МК" пишут в первую очередь ЧИТАЕМЫЙ и сопровождаемый код. Поскольку эмбеддинг отличается от программирования ПК, в первую очередь тем, что сэкономленные ресурсы "на привозе" не продашь. Твой код их ни с кем не делит. Если ресурсов достаточно, нужно писать классический, читаемый код. Начинать изгаляться с экономией нужно исключительно тогда, когда ресурсы на пределе. Если "охранник с пистолетом" не стоит за спиной, то лучше взять другой МК, чем поганить код. Стоимость МК сегодня не является определяющей даже в крупносерийном производстве.
Иначе получаются те, карикатурные "эмбеддеры" из статьи на Хабре. Логик знает - из какой. Я ссылку сейчас не найду.
=====================
Логик. Абсолютно нормальный пример. Мне остается только гадать, с манерой коллеги Ркита НЕ ПОЯСНЯТЬ свои тезисы. Думаю, что он на лямбду возбудился. Которая добавит пару тактов при исполнении кода.
Но если убрать лямбду и перенести код обработчиков прямо в свитч, то потеряется читаемость. Я выберу читаемость против пары тактов.
Пояснять он все равно ничего не станет. ;)))
Вот так пишут, если на С++;
За три инструкции в одну строчку, или за >= в любой серьезной компании вставят такого пенделя, что мало не покажется.
Ну я же так и сказал. На лямбду возбудился. ;))
А если еще есть вызовы, то в 10 местах будем эту "одну строчку" писать... и править, при изменении?
Логик же просто иллюстрацию привел. Если бы в коде было ТОЛЬКО то, что он написал, то вариант Ркит-а, конечно рулит.
Ну и парсер тоже отдельная тема. Он есть? А если нет? Не все пишется на ESP32, ты же понимаешь это?
--------------------------------
Ты написал, что вообще не стоит применять стопки колбэков в эмбедде? И Логик и я - не согласны. Как любое обобщение - высказывание ложно. Или я тебя не правильно понял, что возможно.
Если есть хоть 10% вероятности повторного использования кода в проекте, его нужно выделять в отдельное место. Объект, метод, функцию, лямбду - похеру, но отдельно. В примере Логика не было кода действий, поэтому твой вариант рулит. Не так?
Думаю у всех есть опыт анализа чужого "говнокода", где одна и та же последовательность действий повторена в коде в 20+ местах? Особенно этим всратые pHp-шники грешат! Поубивал бы гадов! ;)))))))
Сорри, не заметил про "три инструкции" - ну это ж смешно. Автоформатер расставит их по отдельным строчкам. Это ж пример был просто. ">=" ? Серьезно? Ну и как тогда пользоваться indexof, если ">=" как раз и означает вхождение? Это уж сродни МИСРА, не к ночи её поминать.
За три инструкции в одну строчку, или за >= в любой серьезной компании вставят такого пенделя, что мало не покажется.
В любой серьёзной компании, обративший внимание на такое сразу бы получил дружеское предупреждение от ПМ-а за токсичность. Если бы не унялся - не очень дружеский разговор о причинах желания потратить человекодни на задачу, не дающую фирме прибыли, возможно с предложением лично заняться этой задачей в время свободное от основных оплачиваемых. И не дай бог при этом отламать чего )))) При дальнейшем непонимании к общению подключились бы HR-ы, ответственные за психологический климат команды и начал бы задавать дурные вопросы. Вот дальше этого ни один известный мне не прошёл, возможно и отстранили бы, перевели куда.. Но айтишники обычно соображают что оно того не стоит.
То, о чем ты написал, тоже наблюдается, как правило в остатках НИИ, шарагах и старых фирм, где есть некий "аксакал" который уже глубоко в маразме, в коде и задаче шарит слабо, но его авторитет большой. Что ему остаётся? Проверяет отступы, ищет ошибки в именах идентификаторов, проверяет не боле ли 80 символов в строке, иногда пробелы вставляет, потом удаляет... Работает как может)))) Но разрабы то понимают ситуацию, так что не обижаются даже))) А вот если кто молодой такое отчубучит - очень плохо, сразу подозрение в отсутствии знания и умения, т.к. из всего что нужно делать видит только херню.
Я смотрю, rkit, ты из аксакалов. То, что поиск идёт перебором тебя никак не смутило. В алгоритм не лезеш. Зато три инструкции- проблема!
Но ты же обычный текст пишешь правильно? Начало предложения с заглавной, запятые там где надо, отступы, пустые строки... Так почему же ты в программе так не делаешь? Почему кто то должен голову ломать что бы понять что ты там хотел сказать? На кой это надо, заниматься раскодированием написанного! И вот это как раз и есть культура, иначе это пох*изм или разпи*дяйство писателя.
//пишеш правильно...
не. Не всегда. Главное смысл а не форма. И если у чела сложности из за перечисленных проблем, то на понимание смысла можно и не рассчитывать. Ну серьёзно, поймёт ли глубину философской идеи некой книги человек, у которого сложности вызывает строчная буква на месте заглавной?
//На кой это надо, занимается раскодированием...
Вот. Не надо. Если три инструкции у читающего вызывают необходимость раскодирования, то можно считать, что код написан не для его уровня, внутри ещё сложней все и не надо туда лезть. Для того кто осилит суть три инструкции в строке не должны быть проблемой. Ослиный мостик называется.
не. Не всегда. Главное смысл а не форма. И если у чела сложности из за перечисленных проблем, то на понимание смысла можно и не рассчитывать.
ерунду ты пишешь. Сам для себя ты можешь писать как угодно (хотя тоже непонятно, зачем писать криво?)
Но если ты работаешь в команде - форма зачастую важнее смысла. Твой коллега. который работает с этим же кодом - не должен тратить время на вникание в смысл твоего кода, замусоренный кривой формой. это непроизводительная трата ресурса компании.
Рассказы про неких HR, обращающих внимание на "качество" кода и закрывающих глаза на оформление - это разве что в мелкой шараге , где все по свойски. В крупных конторах все формализовано - ФОРМАлизовано - форма главное. Программиста. который плюет на стандарты оформления кода. принятые в компании - никто держать не будет даже если по смыслу его код гениален. Он просто не успеет проявить свою "гениальность" - его выгонят раньше.
Программиста. который плюет на стандарты оформления кода. принятые в компании - никто держать не будет даже если по смыслу его код гениален.
Истинно так, меня с моим дедостилем выгоняют еще на стадии тестового задания, обычно. :)
Я уже смирился и никуда не лезу. :)
пора открывать тему - пишем и оформляем код по фэншую...
пора открывать тему - пишем и оформляем код по фэншую...
Только с разъяснениями почему так "по феншую", а вот так вот уже "не по феншю". Очень даже интересно (мне).
Откровенного бага с >= ни один феншуй и не заметил.