Почему виснет совершенно простой код?!!
- Войдите на сайт для отправки комментариев
Ср, 20/05/2015 - 11:39
Добрый день, уважаемые форумчане!
Помогите разобраться в простом коде.
Код работает следующим образом: из последовательного порта считываются произвольные символы. Командой atoi() преобразуются в целое число и значение возвращается функции readingFromSerial(). Если же я удаляю часть кода (выделил коментарием), то модуль ReadingFromSerial() запускается до строки while (Serial.available() > 0) { и виснет. Как так?!! Сразу скажу что readingFromSerial() я пробовал вызывал из void Loop() и из void serialEvent(). Эффект тот же.
Помогите!!!
#include <stdlib.h> void setup() { Serial.begin(9600); Serial.println("*********START**************"); } int ReadingFromSerial(){ char* text; char txt[20]; int T, Q; //**************** на этом месте прога останавливается если удалить часть кода while (Serial.available() > 0) { if (T<19){ txt[T] = Serial.read(); Serial.print("what reading"); Serial.print('\t'); Serial.println(txt[T]); T++; txt[T]='\0'; } } //=======если удалить эту часть кода if (T > 0){ text=txt; Q = atoi(text); Serial.print(text); Serial.print(" txt = "); Serial.println(txt); } //=============== вот до этой строки return(Q); } void loop() { delay (50) ; /* можно и от сюда вызывать функцию Serial.println( ReadingFromSerial() ); */ } void serialEvent() { Serial.println("Event!!!!") ; Serial.println( ReadingFromSerial() ); }
Ответ в строке 14, если T >= 19, то данные из сериала не считываются, хотя они там есть. И так до бесконечности
UPD: и ещё, локальные переменные надо инициализировать, ибо там мусор из стека.
Да нет же! даже при вводе в порт 1 символа прога виснет на 13 строчке и ни разу не считывает данные из порта. Меня больше волнует вопрос: почему полный код работает правильно (будь то T> или <19), а с удалением части кода - виснет? Где логика? )
Инизиализировать - это задать начальное значения? Спасибо за дельный совет. Я почему то думал что при объявлении по умолчанию всё равно 0.
Только что проверил. Задал начальные значения для T и Q - и всё заработало!!! Это ж надо же как "мусор из стека" влияет на работу!
Только что проверил. Задал начальные значения для T и Q - и всё заработало!!! Это ж надо же как "мусор из стека" влияет на работу!
Причем тут мусор из стека?
При таком вольном обращении с памятью - конечно будет виснуть.
Вы и дальше будете иметь зависания, ибо значение переменной T вы ничем не ограничили, а массив, индексом для которого эта переменная является, имеет у вас фиксированную размерность.
Согласен. Но теперь дальнейшая отладка и устранение зависания (ограничение Т и т.д.) уже проще - логика стала понятной
ЗЫ: Тяжело соскочить с VB )...
Скажем к примеру так:
Не присвоив значение переменной вы можете в ответ получить любое случайное число.
Так понятнее?
какие все стали умные, когда автор сам нашел свою ошибку )))
не инициализируются нулём только регистровые и локальные нестатические переменные.
глобальные инициализируются нулем. хотя, коненчо, правильнее инициализировать явно - правило хорошего тона.
Специально скопировал представленный в начале код. Ни символа не изменял - всё работает, не смотря на то что локальные переменные я не инициализировал. Главное чтобы не больше 19ти символов в порту было. Но не в этом дело. А потом удалил чать кода, который я пометил - и всё! Прога остановилась на 13й строчке. На 12й строчке я прописал: Serial.println("Event") ; При выполнении программа выдала в порт "Event" и остановилась.
И ни разу ни считала порт - будь то один символ или десять. Почему?!!
Мне стало любопытно - а чему при этом равна Т если она не инициализирована и заменил 12ю строчку на Serial.println(T) ;
и... программа опять заработала без глюков!!!
Анализируя свои действия я пришел к выводу что моя прога должна была изначально НЕ работать (!!!), т.к. Т действительно не инициализирована, а значит условие T<19 не возможно проверить и соответственно выполнить тело цикла. Как-то так...
Поймите же простую вещь - "не инициализированные" переменные, на самом деле, означает что они инициализировались каким-то случайным числом.
Это случайное число может оказаться "подходящим" для нормальной работы программы, и тогда вы просто не заметите своей ошибки. Но при любом изменении и перекомпиляции программы случайное число может измениться, и программа снова начнёт глючить.
И не только при перекомпиляции, но и при простом выключении-включении питания - память контроллера заполняется какими-то неопределёнными значениями, а значит, одна и та же программа может работать по-разному.
Так что, да - если хотите писать на C/C++, учитесь аккуратно обращаться с памятью/переменными.