Class String bug: c_str() method return a null pointer

smasson

New member
Hello. I am a new member on this forum. I have been consulting it for a long time with great interest. Yesterday I found what I think is a bug with the Class String.

After creating a String initialized with an empty c string ( String * str = new String (""); ), the c_str () method returns a null pointer with my Teensy. I rather expect a valid pointer to an empty c string.

However if the initialization is done with a non-empty c string and then I reassign an empty c string after, c_str() returns a valid pointer to an empty c string.

The bug seems to have been introduced in the copy method in WString.cpp:

Code:
String & String::copy(const char *cstr, unsigned int length)
{
	if (length == 0) {
		if (buffer) buffer[0] = 0;
		len = 0;
		return *this;
	}
	if (!reserve(length)) {
		if (buffer) {
			free(buffer);
			buffer = NULL;
		}
		len = capacity = 0;
		return *this;
	}
	len = length;
	strcpy(buffer, cstr);
	return *this;
}
With the addition of the condition if (length == 0) the buffer is never allocated with initialization of an empty c string.
I imagine the goal here was to avoid allocating a buffer if the String is empty. This is good for optimization but it introduced the bug for c_str().

To avoid this I propose to modify c_str() in WString.h so as to force the method to return a pointer to an dummy empty static c string if the buffer has never been allocated.
Like this:

static char dummy = 0;
const char * c_str() const {return (buffer == NULL) ? &dummy : buffer; }

With this simple modification in a future version the optimization remains and c_str() guarantees never return a null pointer.
 
It's just a bit older copy of Arduino's WString. Solution could be simply make an upgrade of code base to be up to date with current Arduino code base.

In the latest Arduino core it seems to be much harder to create instance, that returns nullptr from c_str().

However I can imagine for example
Code:
char * ptr = nullptr; String str { ptr };
which results into nullprt returned by c_str() (in latest Arduino codebase). However it's not so easy to archieve it, as you can't just pass the nullptr without explicit cast to char* due to ambiguity. The empty string in current teensy code base is way easier.
 
Thanks for your reply KIIV.

My solution for the moment is quite simple. I never use the c_str () method of the Class String directly. Instead, I call a global function that I created that checks if c_str () returns a null pointer and if so it replaces it with a valid pointer to a null character.

Code:
const char    *c_str(const String &Str)
{
  static const char dummy = 0;
  const char  *cstr = Str.c_str();

  return !cstr ? &dummy : cstr;
}

Example:
char * ptr = nullptr; String str { ptr };

char *cstr = c_str(str); // The global c_str() function return valid pointer to static dummy variable.
 
I agree, this is a bug and should be fixed.
Don't you want to create a Pullrequest @ github to fix this?

Otherwise i can take a look.
 
In theory it could've been fixed in teensy and teensy3 core too :D

Maybe little sync with Arduino core wouldn't hurt (where is much less likely to return nullptr from c_str). Btw: they even fixed possible deadlock with HardwareSerial.print inside of ISR (for AVRs) many years ago.
 
In theory it could've been fixed in teensy and teensy3 core too :D

Fixed on Teensy 3.x too.

https://github.com/PaulStoffregen/cores/commit/2cd86801aed85e1b2f700c8c3f444313bd95b8cd


Maybe little sync with Arduino core wouldn't hurt (where is much less likely to return nullptr from c_str).

Their code has changed quite a lot. Their invalidate() function does set the pointer to NULL.

For now, I'm going to leave things as they are and address incompatibilities as they arise.


Btw: they even fixed possible deadlock with HardwareSerial.print inside of ISR (for AVRs) many years ago.

Like so many issues, I will only work on this when someone reports it with a test case. If you want me to dig into this, please start a new thread with code to reproduce the problem.
 
And welcome back Frank!!

Thank you.

Trying to get up to date here.

I made a short trip into the Arduino-ESP32 world.
The progress there is impressive.
For communication things it is (now) a well supported platform, the documentation has become good and for everything you can find stable libraries.
But uploading is still a pain (slow), compiling takes ages - especially if you use web servers and clients, spiffs, nvs and more. But everything you need is there.

The Teensy platform is still more fun. Even if some things are more complicated or missing.
For the ESP I liked rtos (we NEED that), and the preferences lib.
 
Back
Top