1

I've encountered something odd which I don't understand in this code:

#include <EEPROM.h>

struct Settings {
  char stringy[24] = "initial";
};

void setup() {
  Serial.begin(74880);
  EEPROM.begin(100);


  Settings s;
  strncpy(s.stringy, "a string", sizeof(s.stringy));

  EEPROM.put(0, s);

  Settings s3 = readSettings();
  Serial.println(s3.stringy);
}

Settings& readSettings() {

  Settings s2;
  Serial.println(s2.stringy);
  EEPROM.get(0, s2);

  delay(1);

  return s2;
}

void loop()
{
  
}


EEPROM implementation is this: https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM

The code as it is prints:

initial
a string

But if I comment the delay(1), then it prints

initial
initial

What? The delay(1) can be replaced with seemingly an any other statement.

What's going on here? Where is this strange async-seeming behaviour coming from?

If I make readSettings return a Settings object instead of Settings& then the issue also goes away.

I'm confused, what am I missing here?

halfer
  • 19,824
  • 17
  • 99
  • 186
Andrew Bullock
  • 36,616
  • 34
  • 155
  • 231
  • `readSettings` return a reference to a *local* variable. A variable whose life-time ends when the function ends (making the reference invalid immediately). Doesn't your compiler complain? – Some programmer dude Oct 23 '20 at 17:22
  • @Someprogrammerdude ok... (a) what should i be doing, (b) why does `delay(1)` affect this? – Andrew Bullock Oct 23 '20 at 17:23
  • 1
    Return *by value*. And *undefined behavior* (which is what you have) could lead to anything happening. – Some programmer dude Oct 23 '20 at 17:24
  • ok, but wont that wastefully create a copy? And still, why does `delay` affect this, regardless of the correctness of your first statement? thats why im so confused :/ – Andrew Bullock Oct 23 '20 at 17:26
  • 1
    [Undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) is undefined. It could lead to software crashes, the computer exploding, summoning [nasal demons](http://www.catb.org/jargon/html/N/nasal-demons.html), or seemingly working fine. – Some programmer dude Oct 23 '20 at 17:31
  • And please do some research about *copy elision* and *return value optimization*. – Some programmer dude Oct 23 '20 at 17:32
  • it changes that anything what can happen – Juraj Oct 23 '20 at 17:38
  • @Someprogrammerdude want to post this as a proper answer, not understanding Copy Elision was my issue – Andrew Bullock Oct 23 '20 at 17:40
  • Maybe when I don't have a feverish band almost sleeping baby in my lap... ;) – Some programmer dude Oct 23 '20 at 17:48
  • 3
    @AndrewBullock Noooo, your problem was that you returned a local variable by reference, not that you thought there would be a copy but there isn't. Even if there wasn't copy elision and you actually had to do a copy, you should still not return a local variable by reference. There's really no reason to try to avoid copying small bits of data like that. Your processor can copy 24 bytes pretty quickly, trust me. – Anonymous1847 Oct 23 '20 at 18:42
  • @Anonymous1847 so are all local variables "deleted" when their local scope ends, even if ive taken a reference to it (via tha return)? – Andrew Bullock Oct 24 '20 at 10:04
  • @AndrewBullock they are not deleted, which is why it sometimes works, but the memory is free to be used for something else. On a desktop operating system this code would fail spectacularly consistently, but because you don't have loads of other processes running on here it just happens to work sometimes.. – JeffUK Dec 02 '20 at 23:31

0 Answers0