Global variable randomly changes value after receiving MQTT command

Thread Starter

zazas321

Joined Nov 29, 2015
936
Hello. Something really really weird started to happen to my ESP32 devices. I am receiving MQTT commands from my raspberry PI.
number_to_pick is global variable and set to 0

I have a retained message that the message receives everytime it powers up. During that message, number_to_pick is not being modified, but somehow its value changes???

1600931944933.png


Code:
  if (strcmp(topic,item_inside_topic) == 0){ //if number_to_pick received, means the complecataion has been scanned and initiate the pick_to_light

    if(number_to_pick >0){
      toggle_led_strip(yellow,1);
    }
    
    else if(strncmp(current_status, "PILDYMAS", 8)==0){
      toggle_led_strip(purple,1);
      parse_item_inside((char*)payload);
      item_inside.updated_quantity = item_inside.quantity; // THIS IS UPDATED QUANTITY
      strcpy(current_status,"IDLE");
      item_inside.quantity = item_inside.previous_quantity+item_inside.updated_quantity;
      create_JSON_object_pildymas("global/device_status/Quantity_update",false);
      Quantity_update_flag=1;
      return;
    }
        parse_item_inside((char*)payload);
        item_inside.previous_quantity = item_inside.quantity; 
      
  }
  
}
See the code below, since the current_status initially is not set to "PILDYMAS" the last 2 lines of code will be executed where I parse the item_inside mqtt message.

Code:
void parse_item_inside(char* payload){
Serial.print("numer_to_pick4=");
Serial.println(number_to_pick);
    cJSON* jsonObj = cJSON_Parse((char*)(payload));
  // Get pointer to specific field in JSON object
    cJSON* serial = cJSON_GetObjectItem(jsonObj, "Serial");
    cJSON* quantity = cJSON_GetObjectItem(jsonObj, "Quantity");
    cJSON* state = cJSON_GetObjectItem(jsonObj, "Status");

     //Get integer value - other fields allow access to strings, floats etc.


    strcpy(item_inside.serial,serial->valuestring);
    item_inside.quantity = quantity->valueint;
    strcpy(item_inside.state,state->valuestring);
    if (strncmp(item_inside.state, "NEXT", 4) == 0){
      Serial.println("Raspberry PI confirms that NEXT command was received");
      confirmation_counter=0;
      next_flag = 0;
    }

    if (strncmp(item_inside.state, "DONE", 4) == 0){
      Serial.println("Raspberry PI confirms that DONE command was received");
      confirmation_counter=0;
      done_flag = 0;
    }

    if (strncmp(item_inside.state, "Quantity_update", 15) == 0){
      Serial.println("Raspberry PI confirms that Quantity_update command was received");
      confirmation_counter=0;
      Quantity_update_flag = 0;
    }

Serial.print("numer_to_pick5=");
Serial.println(number_to_pick);
// Delete JSON object (don't forget this)
  cJSON_Delete(jsonObj);

    }
As you can see from my parse function, It does not have any code to change the value of number_to_pick. From the Serial monitor you can see that at the beggining of the function numer_to_pick4 is still 0, however, at the end, numer_to_pick5 is set to 6648929. The only thing that happens between numer_to_pick4 and numer_to_pick5 is the Raspberry PI confirmation that the message has been received, there is nothing to do with the number_to_pick value in either of these functions.

Also, the value is always 6648929.

Could someone help me understand why would that happen???
 

Ajith-N

Joined Sep 14, 2020
31
Well, 'C' has no bounds checking, so program errors can overwrite any part of memory. Pointer arithmetic can make pointers point pretty much to anywhere in memory, including global variables. Not surprising, but surely very hard to debug.
 

Thread Starter

zazas321

Joined Nov 29, 2015
936
Ok I believe I found the problem which I thought was really weird.
In my JSON format message I use a variable named "Status" which is declared as char [10]. However, the string that I am passing is longer than 10 characers ("Quantity_update"). I believe thats what caused the issue
 

MrSoftware

Joined Oct 29, 2013
2,202
Ok I believe I found the problem which I thought was really weird.
In my JSON format message I use a variable named "Status" which is declared as char [10]. However, the string that I am passing is longer than 10 characers ("Quantity_update"). I believe thats what caused the issue
Another gotcha you're bound to run into; most C string routines expect a zero '\0' at the end of the string. If there is no zero terminator at the end, the routine will just continue on through memory until it fines a zero, or until something crashes. If it's a string copy routine then not only can you overrun your source buffer, but you can also overrun your target buffer and overwrite memory just like what you're seeing here. If you need a 10-character string, allocate room for 11 so you can fit the zero at the end.

Note there are newer safer string routines in more up to date libraries that include the size of the buffer as an input parameter. These help prevent overrunning the buffer. For example strcpy() is replaced by strcpy_s().
 

AlbertHall

Joined Jun 4, 2014
12,347
Is this a safe strcpy for compilers that don't have strcpy_s?
Code:
void strcpy_s(char *Dest, uint8_t DestSize, char *Src)
{
    strncpy(Dest, Src, DestSize);
    Dest[DestSize - 1] = 0;
}
 
Top