unwanted String clear

Hy

I have a question concerning something strange that I have encountered.
I have written a code of which a piece is the following:

while (!stopMeasurements){
      prevAllDistanceMeasurements=allDistanceMeasurements;
      distance=Lidar.getDistance(); // returns 1 distance sample

      Serial.print("Measured distance: ");
      Serial.println(distance);
      Serial.print("EV3.getAmountOfData(): ");
      Serial.println(EV3.getAmountOfData());

      EV3.setAmountOfData(EV3.getAmountOfData()+1);
      allDistanceMeasurements=allDistanceMeasurements+distance+"/";
      if (allDistanceMeasurements.length()<prevAllDistanceMeasurements.length()){

        Serial.println(prevAllDistanceMeasurements);
        Serial.println(distance);
        Serial.println(prevAllDistanceMeasurements+distance+"/");
        Serial.println(allDistanceMeasurements);
        Serial.println(allDistanceMeasurements.length());
        Serial.println(prevAllDistanceMeasurements.length());

        //allDistanceMeasurements has been reseted because it was too big. Store the prevAllDistanceMeasurements such that it is not lost.
        EV3.storeData(prevAllDistanceMeasurements);
        allDistanceMeasurements=distance+"/";

        Serial.print("Saved. allDistanceMeasurements: ");
        Serial.println(allDistanceMeasurements);

        prevAllDistanceMeasurements="";
      }
      stopMeasurements=EV3.checkEndRequest();
    }

This gives me then the following response. (the text starting with sizeof() and ending with 20 (above “saved.”) is due to print commands in the method, so neglect those lines).

My question is why the String object allDistanceMeasurements is cleared (this is the line above the 0 in the figure (see link)) while printing out prevAllDistanceMeasurements+distance+"/" (which should be what allDistanceMeasurements is at that moment) is not cleared.

Thanks

Please show the declarations for these two variables:

      prevAllDistanceMeasurements=allDistanceMeasurements;

You might be just making one point to the other instead of actually copying all the contents of "all" into "prevAll".

The declarations of these 2 are situated before the void loop(){ .

#include "EV3Communicate.h"
#include "LidarSensor.h"
#include "SoftwareSerial.h"

LidarSensor Lidar;
SoftwareSerial ss(10,11);
EV3Communicate EV3(&ss);


void setup() {
  // put your setup code here, to run once:
  EV3.begin(4800);
  Lidar.begin();
  Serial.begin(9600);
}

boolean measuringData=false;
String messageBegin="";
String messageEnd="";
boolean stopMeasurements=false;
int distance=0;
String allDistanceMeasurements="";
String prevAllDistanceMeasurements="";


void loop() {
messageBegin=EV3.readIn();
  
  if (messageBegin.equals("Begin")){
    Serial.println("Begin/ received. Starting measurements:");
    EV3.dataSend=false;
    boolean succesAdded=true;
    while (!stopMeasurements){
      prevAllDistanceMeasurements=allDistanceMeasurements;
      distance=Lidar.getDistance(); // returns 1 distance sample
      Serial.print("Measured distance: ");
      Serial.println(distance);

Actually, I already solved this problem by changing

allDistanceMeasurements=distance+"/";

to:

int succesAdded=allDistanceMeasurements.concat(String(distance)+"/");

However I have now a new problem of which I suspect it is closely related to this one. My problem now is: when the String becomes too large, I want to pass it to a function for storing it. However before passing the string to the function it is not empty, but when I print the string inside the function, I get an empty string. Does someone know why this is?

So the code for this is:

      int succesAdded=allDistanceMeasurements.concat(String(distance)+"/");
      EV3.setAmountOfData(EV3.getAmountOfData()+1);
      if ((allDistanceMeasurements.length()<prevAllDistanceMeasurements.length())|| (!succesAdded)){
        Serial.print("allDistanceMeasurements: ");
        Serial.println(allDistanceMeasurements);
        Serial.print("prevAllDistanceMeasurements: ");
        Serial.println(prevAllDistanceMeasurements);
        EV3.storeData(prevAllDistanceMeasurements);
        allDistanceMeasurements=distance+"/";
        /*Serial.print("Saved. allDistanceMeasurements: ");
        Serial.println(allDistanceMeasurements);*/
        prevAllDistanceMeasurements="";
      }

and the code of the function storeData is:

void EV3Communicate::storeData(String newData){
	Serial.print("newData: ");
	Serial.println(newData);
	int lengthStorage=sizeof(dataStorage);
	int emptyPos=getEmptyPos();
	Serial.print("emptyPos: ");
	Serial.println(emptyPos);
	Serial.print("storageFull: ");
		Serial.println(storageFull);
	if (!storageFull){
		dataStorage[emptyPos]=newData;
		Serial.println(dataStorage[0]);
		Serial.println(dataStorage[0].length());
		Serial.println(dataStorage[emptyPos].length());
	}else{
		Serial.println("DataStorage is full. Immediate data transfer needed");
		immediateDataTransfer();
	}
}

For the shown Serial.print commands, the response is this

Thanks

You're probably running out of memory trying to allocate a copy of the String. Passing a pointer or a reference (e.g. a String& instead of a String) might "fix" it, but then the very next String operation might start failing instead. Assuming you're on an Uno, you only have 2kb of RAM, which makes things like String quite hazardous. Not only do they greatly ease the task of dealing with strings, the also greatly ease the task of consuming memory, and the temporary strings you end up creating by doing things like...

int succesAdded=allDistanceMeasurements.concat(String(distance)+"/");

...often end up leaving behind unusable holes in memory--"heap fragmentation". You'll want to read up on String's "reserve()" method, and just generally try to cut down on the number of temporary strings and string copies you're creating. Or try to imagine a way to do what you want without String, which is common advice. And there are many other strategies and helpful tools for reducing the amount of RAM your sketch consumes. Look into the "F()" macro, which eases the task of putting your constant strings into flash.

Or get an Arduino with more RAM, which is another "fix" (until it isn't).

Indeed, I also came to the same conclusion. That is why I use global variables for the most important ones (like receiving messages and sending messages) such that there is always room for it left.

Thanks for the help.