0

For a RF project I need to split payload for a max predefined chunk size. For that I created a RFmsg struct.

The unexplained part I need help in is why when I create a local instance of RFmsg, its contents are remain in tact after function is recalled? is it a struct "thing"? or something else I'm missing ?

To solve that I know that wiping struct content after initiating will solve that, but I'm want to be sure.

for that I share a minimal code that:

  1. void newMSG(char *msg) simulates the splitting part of a long msg input.
  2. void printStrcut_content(RFmsg &_payload) prints struct's content.
  3. output show that only after boot, its content are gibberish, but after that, it shows the content of last struct update.

CODE:

#include <Arduino.h>
#define MSG_LEN 10
#define DEVNAME_LEN 8

char *devName = "TEST";

struct RFmsg
{
    int msg_num;
    int tot_msgs;
    int tot_len;
    char payload[MSG_LEN];
    char dev_name[DEVNAME_LEN];
};

void newMSG(char *msg)
{
    RFmsg _payload;
    printStrcut_content(_payload);

    _payload.tot_len = strlen(msg);
    strcpy(_payload.dev_name, devName);
    _payload.tot_msgs = (int)(_payload.tot_len / MSG_LEN);

    if (_payload.tot_len % MSG_LEN > 0)
    {
        _payload.tot_msgs++;
    }

    for (uint8_t i = 0; i < _payload.tot_msgs; i++)
    {
        strcpy(_payload.payload, "");
        for (uint8_t n = 0; n < MSG_LEN; n++)
        {
            _payload.payload[n] = (char)msg[n + i * MSG_LEN];
        }
        _payload.payload[MSG_LEN] = '\0';

        Serial.print("chunk #");
        Serial.print(i);
        Serial.print(": ");
        Serial.println(_payload.payload);
    }
}
void printStrcut_content(RFmsg &_payload)
{
    Serial.print("LEN: ");
    Serial.println(_payload.tot_len);
    Serial.print("PAyLOAD: ");
    Serial.println(_payload.payload);
    Serial.print("name: ");
    Serial.println(_payload.dev_name);
    Serial.print("tot_msgs: ");
    Serial.println(_payload.tot_msgs);
}

void setup()
{
    Serial.begin(115200);
    while (!Serial)
        ;
    Serial.println("\nStart");
}
void loop()
{
    newMSG("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    delay(5000);
}

OUTPUT:

Start
LEN: 36
PAyLOAD: UVWXYZ
name: 
tot_msgs: 4
chunk #0: 1234567890
chunk #1: ABCDEFGHIJ
chunk #2: KLMNOPQRST
chunk #3: UVWXYZ
LEN: 36
PAyLOAD: UVWXYZ
name: 
tot_msgs: 4
chunk #0: 1234567890
chunk #1: ABCDEFGHIJ
chunk #2: KLMNOPQRST
chunk #3: UVWXYZ
LEN: 36
PAyLOAD: UVWXYZ
name: 
tot_msgs: 4
chunk #0: 1234567890
chunk #1: ABCDEFGHIJ
chunk #2: KLMNOPQRST
chunk #3: UVWXYZ
3
  • 1
    I also would guess that the struct just always lands on the same memory space, thus retaining the value. Though you cannot count on that. You don't have any control over that.
    – chrisl
    Apr 5, 2022 at 6:53
  • @Juraj since it is a tiny part of much larger code, I was shocked to see this behavior repeats, at it was intentionally kept some how. what do you recommend ?
    – guyd
    Apr 5, 2022 at 6:54
  • 1
    Just initialize the struct variable with known values at the start of your function. You just did see that behavior because you didn't do that. You should always initialize variables in functions. Only global variables get initialized implicitly.
    – chrisl
    Apr 5, 2022 at 7:33

1 Answer 1

3

As described in the comments: Your local struct variable probably always is placed in the same space in memory and this part of the memory isn't overwritten by your program. When declaring local variables they are not implicitly initialized (written with a value). If you don't initialize the variable yourself, its value will be whatever data is currently in that memory space.

The compiler optimizes your code and also decides on where to place variables on the stack. In this case it is always placed at the same memory space, but you cannot count on that. It is undefined behavior and any change to your program can also change that fact. And you don't have any control over that.

This is the reason, why you should always initialize local variables before reading them.

what do you recommend ?

Just initialize the members of that struct variable before using them. Set all members to a value. You can even do that in one step together with declaring it:

RFmsg _payload = {1, 2, 3, "payload", "devname"};
1
  • 1
    Just to clarify, undefined behaviour does not necessarily mean there will be zeroes there or any specific thing at all. And under certain circumstances what is there might be the same thing that was there the previous time the function was called. If you decide to not bother initialising variables because "it seemed to work last time" you will eventually find that a change to your code will come back to bite you.
    – Nick Gammon
    Apr 11, 2022 at 10:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.