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

 
 
> Внутри Case не присваивается значение глобальной переменной, При вызове функции внутри Case
Димон Безпарольн...
сообщение Jul 31 2017, 13:07
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Весьма запутано, постараюсь объяснить.

Код
            case(OpenTCP):                        //Открытие TCP
                {                                //
                    printf("\rOpen TCP Session\r");//    
                    GSM_State_Mashine = ConnMQTT;//Успешно
                    GSM_Mashine_Errors = 0;        //
                    int T =    GPRSConnect1(TCP, MQTT_BROKER_SERVER, PORT, DEFAULT_TIMEOUT*8, DEFAULT_INTERCHAR_TIMEOUT*5);
                    if(!T)                         //
                        {                        //Не успешно
                            printf("\rError TCP Open... Try Again...\r");//    
                            int T =    GPRSClose();//
                            GSM_Mashine_Errors++;//
                            break;                //
                        }                        //
                    GSM_State_Mashine = ConnMQTT;//Успешно
                    GSM_Mashine_Errors = 0;        //
                    printf("\rTCP Session Open\r");//
                    break;                        //


Если ставить GSM_State_Mashine = ConnMQTT после вызова GPRSConnect1, то в переменной GSM_State_Mashine остается старое значение и этот case выполняется вечно.

Сама функция GPRSConnect1 и вызываемые ей функции никакого отношения к переменной GSM_State_Mashine не имеет. Причем перед выходом из функции, содержащей этот switch (GSM_State_Mashine) присвоение есть, но за ней (снаружи этой функции) эта переменная имеет старое значение!

Пока вышел из положения присваивая значение GSM_State_Mashine = ConnMQTT; до вызова функции. Так работает. После вызова - нет. Что ж за глюк такой?

Переменная объявлена глобальной volatile unsigned int GSM_State_Mashine = 0;//

Сообщение отредактировал Димон Безпарольный - Jul 31 2017, 13:10
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 24)
alexey123_45
сообщение Jul 31 2017, 13:36
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 69
Регистрация: 1-03-13
Пользователь №: 75 850



А если в этом case поставить точку останова и пойти по шагам попадете на эту строчку, после вызова функции?

Сообщение отредактировал alexey123_45 - Jul 31 2017, 13:38
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Jul 31 2017, 15:11
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(alexey123_45 @ Jul 31 2017, 17:36) *
А если в этом case поставить точку останова и пойти по шагам попадете на эту строчку, после вызова функции?

Да. Все тоже самое.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Jul 31 2017, 17:18
Сообщение #4


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Димон Безпарольный @ Jul 31 2017, 16:07) *
Весьма запутано, постараюсь объяснить.

Код
...
                    int T =    GPRSConnect1(TCP, MQTT_BROKER_SERVER, PORT, DEFAULT_TIMEOUT*8, DEFAULT_INTERCHAR_TIMEOUT*5);

..



поставьте в функцию GPRSConnect1 сразу ретурн. если глюкало исчезнет - ищите а) по корректности передаваемых параметров в функцию б) по потрохам самой функции.


удачи вам
(круглый)
Go to the top of the page
 
+Quote Post
scifi
сообщение Jul 31 2017, 17:52
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Напрашивается поставить на эту переменную watchpoint и смотреть, где она свернула не туда.
Go to the top of the page
 
+Quote Post
iosifk
сообщение Jul 31 2017, 19:17
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369



Цитата(Димон Безпарольный @ Jul 31 2017, 16:07) *
int T = GPRSConnect1(TCP, MQTT_BROKER_SERVER, PORT, DEFAULT_TIMEOUT*8, DEFAULT_INTERCHAR_TIMEOUT*5);
if(!T) //


Ведь Т - это число...
А if(!T) подразумевает, что в скобках будет булево выражение - истина или ложь...
А что такое !T по Вашему??? Даже если компилятор воспримет это как битовую инверсию, то это все равно будет число, но не истина или ложь...
Для примера вместо if(!T) сделайте printf( вот этого !T в виде набора битов...


--------------------
www.iosifk.narod.ru
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Jul 31 2017, 19:35
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(iosifk @ Jul 31 2017, 23:17) *
Ведь Т - это число...
А if(!T) подразумевает, что в скобках будет булево выражение - истина или ложь...
А что такое !T по Вашему??? Даже если компилятор воспримет это как битовую инверсию, то это все равно будет число, но не истина или ложь...
Для примера вместо if(!T) сделайте printf( вот этого !T в виде набора битов...

Не понимаю. Весь Paho MQTT в этих if(!T) и работает. И только в одном месте глючит. Проверил. Баз этого if(!T), просто с вызовом тоже глючит.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 31 2017, 20:53
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(iosifk @ Jul 31 2017, 22:17) *
А что такое !T по Вашему???

Вообще-то !T - это такой же точно int, как и T:
Цитата
The result of the logical negation operator ! is 0 if the value of its operand compares
unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int.


Димон Безпарольный, поищите undefined behavior в функции GPRSConnect1.
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Aug 1 2017, 05:28
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(iosifk @ Jul 31 2017, 22:17) *
Ведь Т - это число...
А if(!T) подразумевает, что в скобках будет булево выражение - истина или ложь...
А что такое !T по Вашему??? Даже если компилятор воспримет это как битовую инверсию, то это все равно будет число, но не истина или ложь...
Для примера вместо if(!T) сделайте printf( вот этого !T в виде набора битов...
Если вы плохо знаете Си, то лучше не пишите в темах про Си.
Go to the top of the page
 
+Quote Post
Obam
сообщение Aug 1 2017, 08:16
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663



А где здесь ARM? Треду именно что место в темах про C.


--------------------
Пролетарий умственного труда.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 1 2017, 09:37
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(iosifk @ Jul 31 2017, 22:17) *
Ведь Т - это число...
А if(!T) подразумевает, что в скобках будет булево выражение - истина или ложь...
А что такое !T по Вашему??? Даже если компилятор воспримет это как битовую инверсию, то это все равно будет число, но не истина или ложь...
Для примера вместо if(!T) сделайте printf( вот этого !T в виде набора битов...

Это тяжелое наследство "асемблерности" C. В нём нет булева типа. Поэтому всё целочисленнуказательное что 0 - считается ложным, а все остальное - истинным. Так и живем. sm.gif
-----------
А по сабжу - чудес не бывает. Либо UB, либо битый указатель, либо выход индекса за диапазон, либо стек начал наваливаться на область памяти статических переменных. Ватчпойнты и последовательное выбрасывание кода, помогут разобраться, т.к. в приведенном участке кода ничего криминального не видно.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 1 2017, 11:39
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(Kabdim @ Aug 1 2017, 13:37) *
Либо UB, либо битый указатель, либо выход индекса за диапазон, либо стек начал наваливаться на область памяти статических переменных.

Похоже что именно так.
Go to the top of the page
 
+Quote Post
Aaron
сообщение Aug 1 2017, 12:29
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



берите map-файл проекта с расположением переменных в памяти. И посмотрите, какая переменная в памяти расположена ДО вашей сбойной GSM_State_Mashine в обоих случаях:
- когда "всё работает"
- когда "сбоит"
там, где сбоит - смотрите название переменной и копайте причины её поломки. Возможно неверное приведение типов при работе с указателями или может где-то ещё пораньше в памяти массив лежит, с которым неверно работаете. По крайней мере такой анализ map-файла достаточно быстро проводится, и позволяет быстро находить поверхностные ошибки.

также для того варианта, когда "всё работает" - посмотрите, куда переменная переехала в памяти, предшествующая GSM_State_Mashine - скорее всего, она затирает какие-то несущественные данные, и поэтому вы не замечаете проблем. Так называемый плавающий баг - как правило, он именно вашим описанием и характеризуется, когда от простой перестановки строк кода меняется поведение программы.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 1 2017, 13:37
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(Димон Безпарольный @ Aug 1 2017, 14:39) *
Похоже что именно так.

Кстати может быть бага в компиляторе. Если gcc, то имеет смысл его обновить до старшего минора в используемой ветке. Или наоборот, попробовать предыдущий мажор. Правда с теми же симптомами может быть и UB.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 1 2017, 14:36
Сообщение #15


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(Kabdim @ Aug 1 2017, 17:37) *
Кстати может быть бага в компиляторе. Если gcc, то имеет смысл его обновить до старшего минора в используемой ветке. Или наоборот, попробовать предыдущий мажор. Правда с теми же симптомами может быть и UB.

Нет. Keil 5.17
Go to the top of the page
 
+Quote Post
tvsdig
сообщение Aug 1 2017, 19:54
Сообщение #16





Группа: Участник
Сообщений: 9
Регистрация: 24-11-16
Пользователь №: 94 344



Теоретически может еще влиять включенная оптимизация. Но я за вариант кривые указатели.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 1 2017, 20:35
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(tvsdig @ Aug 1 2017, 22:54) *
Теоретически может еще влиять включенная оптимизация.

На корректный код - не может.

Цитата(tvsdig @ Aug 1 2017, 22:54) *
Но я за вариант кривые указатели.

Маловероятно: кривым указателем можно что-нибудь испортить, а тут состояние машины у ТС остается прежним.

А вообще, можно было бы уже 100500 раз дизассемблировать интересующий фрагмент.

Цитата(aaarrr @ Aug 1 2017, 23:05) *
На корректный код - не может.

Тут я несколько погорячился. Один из немногих встреченных мной "глюков компилятора" (как раз на ARM RVCT) был таки связан с оптимизацией: инлайнилась функция с игнорированием #pragma arm section, и код, предназначенный для выполнения из RAM, выполнялся в результате из флеш.
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Aug 1 2017, 20:48
Сообщение #18


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

Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894



Код
case(OpenTCP):                        //Открытие TCP
                {                                //
                    printf("\rOpen TCP Session\r");//    
                    GSM_State_Mashine = ConnMQTT;//Успешно
                    GSM_Mashine_Errors = 0;        //
                    if(GPRSConnect1(TCP, MQTT_BROKER_SERVER, PORT, DEFAULT_TIMEOUT*8, DEFAULT_INTERCHAR_TIMEOUT*5) == 0)                         //
                        { // эта функция всегда возвращает аргумент в регистре R0, выделять новую переменную для этого не нужно.
                            printf("\rError TCP Open... Try Again...\r");//    
                          //  int T =    GPRSClose();//  не вижу повторного использования Т
                            GPRSClose();
                            GSM_Mashine_Errors++;//
                            break;                //
                        }                        //
                    GSM_State_Mashine = ConnMQTT;//Успешно
                    GSM_Mashine_Errors = 0;        //
                    printf("\rTCP Session Open\r");//
                    break;
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 2 2017, 09:29
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(tvsdig @ Aug 1 2017, 22:54) *
Теоретически может еще влиять включенная оптимизация. Но я за вариант кривые указатели.

Не ставьте телегу вперед кобылы. Это не "оптимизации влияют", а в кривой программе undefined behavior, который при оптимизации раскрывается во всей красе. Людям которые это допускают на регулярной основе стоит подучить язык с которым они работают.
Go to the top of the page
 
+Quote Post
tvsdig
сообщение Aug 2 2017, 14:54
Сообщение #20





Группа: Участник
Сообщений: 9
Регистрация: 24-11-16
Пользователь №: 94 344



Цитата(Kabdim @ Aug 2 2017, 12:29) *
Не ставьте телегу вперед кобылы. Это не "оптимизации влияют", а в кривой программе undefined behavior, который при оптимизации раскрывается во всей красе. Людям которые это допускают на регулярной основе стоит подучить язык с которым они работают.


Отчасти с Вами согласен по поводу подучить язык. Например раздел приоритеты я слабо знаю. Стараюсь использовать скобки.
Но откуда мы знаем с квалификатором объявлена переменная GSM_State_Mashine или без. Поэтому предположил
что ситуация возможна.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 2 2017, 15:10
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(tvsdig @ Aug 2 2017, 17:54) *
Стараюсь использовать скобки.

Вот кстати использование скобок, это не признак незнания. sm.gif Например, вывод здесь:
Код
cout << "foo" + true ? "bar" : "baz";

будет явно не тем который ожидаем, даже для тех кто хорошо знает приоритеты. И даже если есть знание - скобки всё равно лучше ставить, потому что иногда глаз замыливается, да и самому спустя время проще поддерживать код со скобками чем без.
Цитата(tvsdig @ Aug 2 2017, 17:54) *
Но откуда мы знаем с квалификатором объявлена переменная GSM_State_Mashine или без. Поэтому предположил
что ситуация возможна.

ТС в первом же сообщении указал в конце. sm.gif
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Aug 2 2017, 15:19
Сообщение #22


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Димон Безпарольный @ Jul 31 2017, 14:07) *
Весьма запутано, постараюсь объяснить.

Код
int T =    GPRSConnect1(TCP, MQTT_BROKER_SERVER, PORT, DEFAULT_TIMEOUT*8, DEFAULT_INTERCHAR_TIMEOUT*5);
                    if(!T)                         //
                        {                        //Не успешно
                            printf("\rError TCP Open... Try Again...\r");//    
                             int T =    GPRSClose();//


Так у вас там два раза объявляется переменная с одним именем T. И вообще, хоть C99+ позволяет объявлять переменные не в самом начале блока, я бы синтаксически избегал такие вольности.
Go to the top of the page
 
+Quote Post
x893
сообщение Aug 2 2017, 15:30
Сообщение #23


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Это обсуждение курсовой 2 курса ?
Какая то чушь.
Изучите книжку по С, возьмите JLink и посмотрите - где в Ваших знаниях пробелы.
Потом исправьте и посмотрите ещё раз.
Обычно 2-х итераций хватает.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Aug 6 2017, 15:04
Сообщение #24


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Не оптимизация и ничего таккого. В функции GPRSConnect есть вызов itoa1(port, num);.

Поскольку этой функции нет в библиотеке, я взял что - то подобное в Сети. С ней что - то не так, поскольку как только я блокирую этот вызов (не забыв в GPRSConnect поставить выход с положительным результатом return 1), машина состояний исправно переходит на следующий шаг.

Вот с этой функцией что - то не так:

Код
//---------------------------------------------------------------------------------------------------
void reverse(char s[])                            //reverse:  переворачиваем строку s на месте
{                                                //
    int i, j;                                    //
    char c;                                        //
    for (i = 0, j = strlen(s)-1; i<j; i++, j--)
        {                                        //
            c = s[i];                            //
            s[i] = s[j];                        //
            s[j] = c;                            //
        }                                        //
}                                                 //
//---------------------------------------------------------------------------------------------------
void itoa1(int n, char s[])                        //itoa:  конвертируем n в символы в s
{                                                //
    int i, sign;                                //
    if ((sign = n) < 0)                            //записываем знак
    n = -n;                                        //делаем n положительным числом
    i = 0;                                        //
    do                                            //генерируем цифры в обратном порядке
        {                                        //
            s[i++] = n % 10 + '0';                //берем следующую цифру
        }while ((n /= 10) > 0);                    //удаляем
    if (sign < 0)                                //
    s[i++] = '-';                                //
    s[i] = '\0';                                //
    reverse(s);                                    //
}                                                //


Попробую другие варианты из

https://electronix.ru/forum/index.php?showt...=142582&hl=

С ней все так. Эта функция преобразует номер порта 1883 в текст. Так вот, в вызове itoa1(port, num); под нее объявлен массив char num[4];
А нужно 5. Вероятно не хватило места для нуля. При объявлении char num[5]; все заработало исправно.



Сообщение отредактировал Димон Безпарольный - Aug 6 2017, 15:11
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Aug 6 2017, 20:47
Сообщение #25


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



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

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

 


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


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