Problem with eepromex loading a struct (code goes crazy)

Hi.
I have a very strange issue, sorry if i can't explain it well.

I have a program (much bigger than this) that i am making, i noticed that if i make some type of changes in the code it crashes badly, all is tied to the data read from the eeprom!
it seems that it loads the data into the ram in a already used space or something similar.

To use this code and generate the problem do the following:

  1. Take an Arduino UNO, connect a button from pin 7 to ground (i used input_pullup so a resistor might not be needed, but for safety put one)
  2. Load the code, open the serial monitor and keep the button pressed, it will save the default structure to eeprom and will ask you to reset the arduino.

Now you will see this in the serial monitor

93 bytes readed
************* LOOP *****************
temperature=30.60 20.00
Bucketname= BucketName
Bucketkey= BucketKey
Accesskey= ********************************
1
2
3
4
5
6
7
8
9
10
11
12
************* LOOP END *****************

And the loop continues ok.

now just comment out the final

Serial.println("************* LOOP END *****************");
  Serial.println(" ");
  Serial.println(" ");

Or/end 2/3 "toSend" lines in the middle, upload, and your sketch will go crazy, from printing erroneous data in the structure and values to totally screwing up and locking!

Now to make it ok you have 2 options, revert the comments, and upload, and it will be ok, or reset and push the button, the struct will be written in the eeprom again and the program will work.

ATTENTION: if you leave the arduino running with the "no good" eeprom loaded code for long it will go really crazy, and to load another sketch you may need to unplug it, or keep it reset while initiating the load process or similar!

For me this is a real problem since i can't/won't rewrite the eeprom every time i do some changes in the code, and since my code is very large (it runs on a mega) it seems to me that also doing other stuff causes this error, like changing big strings...
This is the sketch.

#include <EEPROMex.h>


double temp[2] = {30.60, 20.00};

struct datastructure {
  byte conf = 1;
  byte dataversion = 3;
  byte mac[6] = {0x90, 0xA2, 0xDA, 0x0D, 0xD5, 0xB6};
  byte ip[4] = {192, 168, 5, 10};
  byte gateway[4] = {192, 168, 5, 3};
  byte subnet[4] = {255, 255, 255, 0};
  byte mydns[4] = {8, 8, 8, 8};
  bool wday[7] = {1, 1, 1, 1, 1, 1, 1};// giorni della settimana per lo schedule dell'ac
  bool ahour[24] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};// 24 hour array
  int offtemp = 28;
  int ontemp = 28;
  int autoontemp = 33;
  bool manualac = 0;
  bool mute = 1;
  String bucketName = "BucketName";
  String bucketKey = "BucketKey";
  String accessKey = "********************************";
  String signalName[2] = {"Reading1", "Reading2"};

};
datastructure data;

String signalData[2];

void setup() {
  EEPROM.setMemPool(0, EEPROMSizeUno);
  pinMode(7, INPUT_PULLUP);

  Serial.begin(9600);
  delay(1000);

  eepromDefaults();

  int x = EEPROM.readBlock(0, data);
  Serial.println((String)x + " bytes readed");
}





void loop() {
  

  Serial.println("************* LOOP *****************");
  signalData[0] = (String)temp[0];
  signalData[1] = (String)temp[1];
  Serial.print("temperature=");
  Serial.print(signalData[0]);
  Serial.print(" ");
  Serial.println(signalData[1]);

  printStructData();


  String toSend = "POST /api/events HTTP/1.1\r\n";
  Serial.println("1");
  toSend += "Host: insecure-groker.initialstate.com\r\n";
  Serial.println("2");
  toSend += "Content-Type: application/json\r\n";
  Serial.println("3");
  toSend += "User-Agent: Arduino\r\n";
  Serial.println("4");
  toSend += "Accept-Version: ~0\r\n";
  Serial.println("5");
  toSend += "X-IS-AccessKey:  " + data.accessKey + "\r\n";
  Serial.println("6");
  toSend += "X-IS-BucketKey:  " + data.bucketKey + "\r\n";
  Serial.println("7");
  String payload = "[{\"key\": \"" + data.signalName[0] + "\", ";
  Serial.println("8");
  payload += "\"value\": \"" + signalData[0] + "\"}]";
  Serial.println("9");
  payload += "\r\n";
  Serial.println("10");
  toSend += "Content-Length: " + String(payload.length()) + "\r\n";
  Serial.println("11");
  toSend += "\r\n";
  Serial.println("12");
  toSend += payload;
  // try to comment the following 3 lines after the first upload + eeprom write with the button
  Serial.println("************* LOOP END *****************");
  Serial.println(" ");
  Serial.println(" ");
  delay(2000);
}




void printStructData(void)
{

  Serial.print("Bucketname= ");
  Serial.println(data.bucketName);

  Serial.print("Bucketkey= ");
  Serial.println(data.bucketKey);

  Serial.print("Accesskey= ");
  Serial.println(data.accessKey);
}


void eepromDefaults(void)
{

  if (digitalRead(7) == LOW)
  {
    EEPROM.writeBlock(0, data);
    Serial.println("Defaults loaded...");
    Serial.println("Please reset");

    while (1)
    {
      //do nothing waiting for the user to reset
    }

  }
}

Are you CERTAIN that you can write objects to EEPROM? I am certain that you can't.

Quit using Strings.

You can write custom objects to the EEPROM using the standard lib, or your EEPROMex lib, however as pauls mentioned, Strings are not suitable for this (you'll have to manually insert the string data).

Strings do not store the data for their string inside their struct/class, only a pointer to it. So when you write a String object you only write the length and pointer to the data (leaving the actual string data behind).

Reading the pointer back into a string object will most likely corrupt something as you have given your String a pointer to possibly already used memory location, and is why the text is missing.

You could use a length value in your struct to store how much string data is needed, and write that object, then simply write the string data (each character) after the struct. When retrieving: read the struct, get the length and then grab the string data.

No actual String objects required, just use arrays of chars (strings). You could use dynamic memory to create the space to read into, either way, still will be better than a String object.

Thank you vey much, i think i got the point.
I tend to use stings as working with char arrays is mo re difficult for me, i'm not very good at programming.

Does strings have other problems outside of my example? what other problems can they generate?
The only other option is to use char arrays? But when a library requires a string as an input or output?

For my code what is the simplest modification you would do to make it work?

Thanks!

I tend to use stings as working with char arrays is mo re difficult for me

That, of course, makes no sense.

A string is a null-terminated array of chars. A String, on the other hand, is a class that does not manage memory well enough to be a part of an Arduino repertoire of functions.

Do NOT use the term string when you mean String. It is incorrect, and pisses people off.

mactsk:
Does strings have other problems outside of my example? what other problems can they generate?

Mysterious crashes because of the limited RAM on the Arduino.

PaulS:
That, of course, makes no sense.

A string is a null-terminated array of chars. A String, on the other hand, is a class that does not manage memory well enough to be a part of an Arduino repertoire of functions.

Do NOT use the term string when you mean String. It is incorrect, and pisses people off.

Sorry i really meant Strings as a class, please be patient to people that is not very familiar with correct terminology.