The HATRED for String objects - "To String, or not to String"

:fearful:

I hope you are aware that the code above is fine as an "extreme" didactic example, but it's definitely a coding horror(1). And the reason is, it's the perfect recipe for spaghetti code :wink:

(1) As in "Code Complete 2"; see Jeff Atwood's blog icon for an effective visual representation of the concept :slight_smile:

Re-entrant code can build up the stack really fast if you're not very, very careful. Remember, UNO has only 2k of RAM for stack and heap space.

Thanks

Coming from Assembly and a bit of basic, I'm trying to get my head around the GNU C compiler and the way it does things.
Been reading the GNU documentation, but sometimes it is "clear as mud" :slight_smile:

K

GoForSmoke:
Re-entrant code can build up the stack really fast if you're not very, very careful.

You're thinking of recursive code?

Right. Functions that call themselves or call others that call them, etc.

It's been a while since I wrote that kind of stuff.

GoForSmoke:
Right. Functions that call themselves or call others that call them, etc.

It's been a while since I wrote that kind of stuff.

Re-entrant is entirely different.

Re-entrant code can be safely called by two different threads at the same time without trashing any global / static variables. They often involve passing of pointers to work areas to the function, so each thread has its own bit of memory.

Something else I wouldn't try with a 328P chip.

Long live the state machine!

GoForSmoke:
Something else I wouldn't try with a 328P chip.

Long live the state machine!

Hell yeah :slight_smile:

I had fun a bit back trying to move a few non-re-entrant library routines (from the printf family) into kernel space on RetroBSD so as to reduce user-process size (kind of a pre-cursor to shared libraries) a bit back... Not nice trying to convert them to re-entrant :wink:

The String class is kind of like training wheels on a bicycle. Babies need them in order to learn how to ride (or code), but as soon as you want to do anything remotely useful you have to take them off and throw them away.

So many of the "Why don't they fix this bug?" complaints could easily be rewritten as:

"Wah! I want to be able to do BMX tricks but I'm scared to let go of my training wheels."

Delta_G:
The String class is kind of like training wheels on a bicycle. Babies need them in order to learn how to ride (or code), but as soon as you want to do anything remotely useful you have to take them off and throw them away.

So many of the "Why don't they fix this bug?" complaints could easily be rewritten as:

"Wah! I want to be able to do BMX tricks but I'm scared to let go of my training wheels."

Wow, another String class whiner! :roll_eyes: Sad that the String class whiners almost never correct/adjust the usually simple they constantly whine about. Sad

Re-entrant would also be where an ISR calls a function.

Say you are in the middle of a Serial.print. A timer interrupt fires. Inside the timer you do a Serial.print (a bad idea, I know). Then the Serial.print function is "re entered". And say inside Serial.print it keeps a variable (eg. for working out how to convert a float). That variable is now changed by the re-entry. So the original one (the one that got interrupted) is now corrupted.

This is another reason why you should keep interrupt service routines short. And why those people that try to work around Serial.print "not working" inside an ISR by adding a line to turn interrupts on, are really shooting themselves in the foot.

Regarding the String class, there is actually a method 'reserve()' that was added with 1.0.

Strange enough totally undocumented on String() - Arduino Reference, but available: Google Code Archive - Long-term storage for Google Code Project Hosting.

I assume with this many dynamic mem allocation probs should be solved if one stays within the reserved memory. And we still can use the richer api. Tested it and it solved my mem leak problem immediately.

Is it love of C++ String, dislike of C string or just not used to C string that drives people to accept the behind your back actions and overhead RAM bytes of C++ String?
Look at all String does to "make it easier" to manipulate text in a number-like manner. Ooooh! Power windows! Hey, turn the car on just so I can open the window! No, that's not inefficient, that's con-veeen-yence!

GoForSmoke:
Is it love of C++ String, dislike of C string or just not used to C string that drives people to accept the behind your back actions and overhead RAM bytes of C++ String?
Look at all String does to "make it easier" to manipulate text in a number-like manner. Ooooh! Power windows! Hey, turn the car on just so I can open the window! No, that's not inefficient, that's con-veeen-yence!

How is your world of horses, buggies, and telegrams/bag phones? C strings are difficult for non programmers like me and appear to somewhat primitive operations compared to the ease of Strings. The "old timers" just don't get it. :wink:

When you're on a horse, you don't expect a steering wheel. An MCU is not a PC.

As far as not knowing C strings, once you understand what a char array with NULL terminator the rest with few exceptions is very straightforward. Yes there is some memorizing of shortened words but strcat() means string concatenation isn't hieroglyphs. Strtok() takes a bit of study but after writing your own array parsing it's no surprise at all. In fact I'd go so far as to say that writing your own version of any of those commands and then refining/rewriting to compact code will teach not only C string but better array handling and coding in general.

The old timers get that an MCU is not a PC. Many of us have written lots of code on both. We know to avoid the traps that the inexperienced walk right into and would rather save others from wasting their time.

I find C++ Strings annoying and unreliable on any platform. In Java I use strings but in C++ I use C-style char arrays.

How is your world of horses, buggies, and telegrams/bag phones?

I saw a feature on TV recently about small-scale logging, using draught horses to extract the timber.
The horses could go where the tractors could not, and their impact on the environment much less, and they could work woodlands too small for ordinary commercial operations.

A reasonable analogy, I think.

The right tool/technique for the right problem.

I'm fairly new to Arduino's, and C coding for that matter as well but have done PHP / MySQL / ASP / HTML coding before.

Can someone please explain to me, what to use if we shouldn't use strings? I see, in many forum posts, where people have problems they're simply being told "don't use strings", and more often than not no sample of an alternative piece of code is given for their problem so the OP in said forum thread doesn't learn anything. And, consequently other newbies don't learn anything useful either and still use strings, since most of the tutorials and forum sample code has them.

C++ Strings are objects that require memory allocation routines (malloc, free) to be called when they are used. For a long time, there was a bug in the implementation of free that the arduino uses that meant that you could run out of memory, so Strings were a dangerous proposition.

More recent versions of the IDE do not have this defect, but manipulating Strings still requires that you free and allocate memory. Given that arduinos have so little RAM, there is still the possibility that you will run out of space or fragment your free memory in such a way that there isn't a big enough contiguous piece to satisfy a request. At this point, your sketch will likely fail in unexpected ways, which will be hard to debug and when you ask for help on the forums you will be told "Don't use Strings".

There's nothing inherently wrong with C++ Strings if you have the memory for them and suitable error handling for dealing with low memory conditions, but for arduino, where you don't have these things, they are not sensible, particularly if your sketch is expected to run in perpetuity. As an alternative, arrays of char let you see exactly what memory you are using without any 'sleight of hand' stuff happening behind the scenes.

RudiAhlers:
I see, in many forum posts, where people have problems they're simply being told "don't use strings" ...

There is a terminology problem here. The posts usually say don't use "String" (which is a specific class) not "don't use strings".

Depending on your requirements you can use an array of characters using the normal C functions like strcpy and strcat. A lot of the Arduinos only have 2048 bytes of RAM, so you don't have a lot of memory for arrays, dynamically allocated strings, or anything else.

At least with manually allocated arrays you know how much memory they are taking. And for constants, you can use strings directly from program memory, eg.

Serial.println (F ("hi there"));

... where people have problems ...

Some problems are caused by the String class, when it had bugs. Some are caused even afterwards because of memory fragmentation. Some are unrelated. However when people post a lengthy sketch, which uses String extensively (as opposed to "strings") one of the first suggestions is to rework without using the String class.

... and more often than not no sample of an alternative piece of code is given for their problem ...

I have examples below which show receiving serial data. They stores strings into static buffers but do not use "String".