Go Down

Topic: The HATRED for String objects - "To String, or not to String" (Read 13 times) previous topic - next topic


with each iteration of the loop does a local variable get created (c/n) and recreated over and over again?

Yes. Automatic local variables are allocated on the stack and thrown away when the stack is unwound at the end of the call. In general, the more tightly you restrict the scope of the data the less chance there is for dependencies and unintended interactions between different parts of your code. This is why use of global data is best avoided where possible, and use of local data and arguments is generally preferred.

With 2k RAM I prefer globals and keeping control of my code. A few locals don't hurt but whole buffers in short often-called functions, it's good to be aware of because some day you might be writing code that needs to be fast rather than 'do it this way every time'.

awareness != mandatory practice

I've likened using C++ Strings on Arduino because C++ Strings are okay on a PC to putting a bathtub on a bicycle just because your house has one. I still feel the same. There's a lot of coding practices I've happily done on PC's that I wouldn't think of doing on Arduino.

I too like the use of global variables in my arduino projects. I like that I can define them all at the top of the sketch with comments on what they represent. I kind of limit my use of local variables to things like the for statements and such. I know this is against the concept of good variable scoping practice that C/C++ encourages programmers to use and does make sense for larger projects where teams of programmers are working on the same application program and have to not step on each others coding functions, but with the limited SRAM space and me being the only one writing the code, global variables work better for me and I haven't heard of a good reason I should avoid them in my Arduino sketches. Sometime I just have to be an outlaw in heart I guess.  ;)



Instead of removing strings, they just have to make about a 1-line change to the library code in free() that has a bug in it. Then some, at least, of the problems will go away.

So what is this one line change? Can it be posted so I can fix my library? I'd just rather fix things instead of hanger flying on the subject. Might eliminate some peoples constant string bashing and often mis diagnosis of problems people are having.
Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)


The problem is that the fix is not to source that is built during normal sketch compilation, but to the libraries provided pre-compiled in Arduino.

Have a look at this bug http://code.google.com/p/arduino/issues/detail?id=857
and this thread: http://arduino.cc/forum/index.php/topic,95914.30.html

Personally, I am not a fan of String, even if some of the problems people run into are due to this bug.  Anything that smells of dynamic allocation has no place, in my opinion, on such a memory-constrained platform.  The problem is that statically allocated and strings and all the string.h stuff is complicated to a beginner.  The String *seems* easy, so you can get something going faster than if you have to grok pointers and in-memory layout of strings and crap just to print hello world.  But I think folks do not appreciate the limits of what you can do with String -- and with lots of other things like arrays and C strings too -- with so little memory, and wind up being forced to learn the details anyhow.

Andy Brown

Part of the problem IS with the String class itself. When you want to append one character to an existing String, the length of the new String is the length of the old String plus the length of the String to append. That amount of space is allocated, and the old String is copied there, then the String to be appended is tacked on, then the old String's space is freed.

No this is not true. String uses realloc() which, if you'd care to read the implementation in realloc.c will always attempt an in-situ block-expansion. For most cases this will result in no pointer change at all and a simple adjustment of the allocated length - usually out into free space in most use-cases on a small system like this. A block-copy is only required if the original allocation either came from the free list and that space is now exhausted or there is a new block allocated in front of the one that needs to be expanded.
Home of the Nokia QVGA TFT LCD hacks: http://andybrown.me.uk

Andy Brown

Memory fragmentation occurs when small variables are removed from the heap to be replaced by larger variables.  The space left by the small variable is too small to accept the larger variable, so the larger variable is instead placed on the top of the heap, causing the heap to grow.  This most often occurs when working with strings and you want to add something to the end of a string (concatenate) or join two strings together.
to be shunned whenever possible.

It's actually quite hard to cause significant memory fragmentation to occur in the avr-libc implementation of the heap. free() will always coalesce blocks above and below the one it's being asked to release to create one larger block in the free list so even a poor String concat implementation that used malloc()+free() instead of realloc() would generally only end up with one block in the free list due to every second free() being coalesced with the previous one and then being big enough to satisfy the next malloc().

If you understand it, use it. If you don't, don't.
Home of the Nokia QVGA TFT LCD hacks: http://andybrown.me.uk

Go Up