Почему виснет совершенно простой код?!!

Dizzz
Offline
Зарегистрирован: 20.05.2015

Добрый день, уважаемые форумчане!

Помогите разобраться в простом коде.

Код работает следующим образом: из последовательного порта считываются произвольные символы. Командой 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() );
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ответ в строке 14, если T >= 19, то данные из сериала не считываются, хотя они там есть. И так до бесконечности
UPD: и ещё, локальные переменные надо инициализировать, ибо там мусор из стека.

Dizzz
Offline
Зарегистрирован: 20.05.2015

Да нет же! даже при вводе в порт 1 символа прога виснет на 13 строчке и ни разу не считывает данные из порта. Меня больше волнует вопрос: почему полный код работает правильно (будь то T> или <19), а с удалением части кода - виснет? Где логика? )

Инизиализировать - это задать начальное значения? Спасибо за дельный совет. Я почему то думал что при объявлении по умолчанию всё равно 0.

 

Dizzz
Offline
Зарегистрирован: 20.05.2015

 Только что проверил. Задал начальные значения для T и Q - и всё заработало!!! Это ж надо же как "мусор из стека" влияет на работу!

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Dizzz пишет:

 Только что проверил. Задал начальные значения для T и Q - и всё заработало!!! Это ж надо же как "мусор из стека" влияет на работу!

Причем тут мусор из стека?

При таком вольном обращении с памятью - конечно будет виснуть.

Вы и дальше будете иметь зависания, ибо значение переменной T вы ничем не ограничили, а массив, индексом для которого эта переменная является, имеет у вас фиксированную размерность.

 

Dizzz
Offline
Зарегистрирован: 20.05.2015

Согласен. Но теперь дальнейшая отладка и устранение зависания (ограничение Т и т.д.) уже проще - логика стала понятной 

ЗЫ: Тяжело соскочить с VB )...

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Скажем к примеру так:
Не присвоив значение переменной вы можете в ответ  получить любое случайное число.
Так понятнее?

Maverik
Offline
Зарегистрирован: 12.09.2012

какие все стали умные, когда автор сам нашел свою ошибку )))

не инициализируются нулём только регистровые и локальные нестатические переменные.

глобальные инициализируются нулем. хотя, коненчо, правильнее инициализировать явно - правило хорошего тона.

Dizzz
Offline
Зарегистрирован: 20.05.2015

Специально скопировал представленный в начале код. Ни символа не изменял - всё работает, не смотря на то что локальные переменные я не инициализировал. Главное чтобы не больше 19ти символов в порту было. Но не в этом дело. А потом удалил чать кода, который я пометил - и всё! Прога остановилась на 13й строчке. На 12й строчке я прописал: Serial.println("Event") ; При выполнении программа выдала в порт "Event" и остановилась.

И ни разу ни считала порт - будь то один символ или десять. Почему?!!

Мне стало любопытно - а чему при этом равна Т если она не инициализирована и заменил 12ю строчку на Serial.println(T) ;

и... программа опять заработала без глюков!!!

Анализируя свои действия я пришел к выводу что моя прога должна была изначально НЕ работать (!!!), т.к. Т действительно не инициализирована, а значит условие T<19 не возможно проверить и соответственно выполнить тело цикла. Как-то так...

Datak
Offline
Зарегистрирован: 09.10.2014

Поймите же простую вещь - "не инициализированные" переменные, на самом деле, означает что они инициализировались каким-то случайным числом.

Это случайное число может оказаться "подходящим" для нормальной работы программы, и тогда вы просто не заметите своей ошибки. Но при любом изменении и перекомпиляции программы случайное число может измениться, и программа снова начнёт глючить.

И не только при перекомпиляции, но и при простом выключении-включении питания - память контроллера заполняется какими-то неопределёнными значениями, а значит, одна и та же программа может работать по-разному.

Так что, да - если хотите писать на C/C++, учитесь аккуратно обращаться с памятью/переменными.