Strings, Teensy Stability

Status
Not open for further replies.

Constantin

Well-known member
Hi guys,

Years ago, I used strings extensively to put together CSV lines to be added to a SD data file. Thanks to Paul and others, the String library hence has become more stable. My question to the brain trust here is whether Strings are stable enough to be used in systems that will be running for months at a time. Especially if they are not fixed-length, they will be used in function calls (i.e. they'd get created and destroyed regularly), etc. Are there methods to help clean up the RAM space to ensure that there won't be issues?

Or in the light of the above constraints is it better practice to create a large fixed-length char array as a global variable and fill that as needed?

Thanks! Constantin
 
I would try to avoid constant reallocations. If reallocations/memory fragmentation are a potential problem for your application is hard to tell, that's going to depend on how large your strings are, how much total memory you are using (and not using) and what other allocations are happening.

You don't need to drop down to char arrays. You can just as well keep a String instance around. You allocate the proper internal buffer size with reserve() once and then just reuse that String instance. Make sure to use reserve(), otherwise some usage patterns can result in memory fragmentation.
 
Thank you and great to know! So I could set a global String variable, reserve a representative size (i.e. 255 bytes) and then and use it over and over by declaring the String = ""?
 
Thank you and great to know! So I could set a global String variable, reserve a representative size (i.e. 255 bytes) and then and use it over and over by declaring the String = ""?
Yes, that will retain the internal buffer.
 
I've had some issues with the Arduino IDE String library working with FreeRTOS, and some people have noted that parts of String() don't work as advertised together with FreeRTOS.

I've done some investigation, and created a work around for the issues, but I'm not the author of String() and I don't fully understand why the two libraries are interacting poorly.

One issue is that converting a function returning an int to a String, within the String(), doesn't work.
And also, it doesn't seem to work unless there is a concatenation as well.

Github reference to the Issue

Any thoughts or tips on what is happening?

Working:
Code:
int analogValue = analogRead(A0);
sensorValue = "is: " + String( analogValue );

Not working:
Code:
sensorValue = String(analogRead(A0)); // OR
sensorValue = String(analogRead(A0), DEC);


Complete code for reference:
Code:
#include <Arduino_FreeRTOS.h>

void TaskAnalogRead( void *pvParameters );

String sensorValue; // Make the sensorValue a Global Variable

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);

  sensorValue.reserve(255); // Reserve a fixed space, larger than the maximum length to avoid reallocation.

  // Now set up a Task to run independently.
  xTaskCreate(
    TaskAnalogRead
    ,  (const portCHAR *) "AnalogRead"
    ,  128  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL );

  // Now the Task scheduler, which takes over control of scheduling individual Tasks, is automatically started.
}

void loop()
{
  // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void TaskAnalogRead( void *pvParameters __attribute__((unused)) )  // This is a Task.
{
  for (;;)
  {
    // read the input on analog pin 0:

    int analogValue = analogRead(A0);
    sensorValue = "is: " + String( analogValue );

    // sensorValue = String( analogValue );
    // sensorValue = String(analogRead(A0));
    // String sensorValue = String(analogRead(A0), DEC);

    Serial.print("Address: ");
    Serial.print(int(&sensorValue), HEX);
    Serial.print("  Length: ");
    Serial.println(sensorValue.length());

    // print out the value you read:
    Serial.print("Sensor Value ");
    Serial.println(sensorValue);

    vTaskDelay(10);  // one tick delay (150ms) in between reads for stability
  }
}
 
@feilipu

I wouldn't be so quick blaming the String library. My first guess at whats going on would be that your FreeRTOS port is screwing up memory allocation and either malloc/realloc is failing or a stack overflow is happening.
 
@feilipu

I wouldn't be so quick blaming the String library. My first guess at whats going on would be that your FreeRTOS port is screwing up memory allocation and either malloc/realloc is failing or a stack overflow is happening.

Thanks for the thoughts.

Yes, I agree that it is a memory allocation issue. And, I'm not blaming String() library, as it clearly works well when used by itself.
My difficulty is trying to identify what part of the two libraries interacting poorly.

Moving the String declaration to Global, and then reserve() space should make any stack overflow or memory (re)allocation issues go away. But, it doesn't completely solve things, as the conversion from int to String still doesn't work unless there is a simultaneous String literal concatenation.

I'm fairly sure it is not a stack overflow, because there is a assert routine that catches Task stack overflows. Possibly, the C stack is overflowing, and I'll check for that. But the issues also happen on a 1284p device with 16kB of memory, so it is not likely.

Anyway, I'll continue to dig.
 
Status
Not open for further replies.
Back
Top