On AVR the String class won’t allocate memory if the operation would result in less than 128 bytes free. That’s how it’s coded.
I'm so used to allocating (malloc()) all the global variables like char and then passing pointers to the functions. I usually used minimal additional space in my functions. Maybe I'll be limited by the minimal RAM space in the ATmega328 in doing that if I decide to make a new Stringless program. I'll see what my latest last resort modification does to those crashes before a restart a new program from scratch.
If you're used to using malloc, you can avoid The Dead Pool of leakage that the String copy constructor can cause you. It's still risky though because the Nano has so little memory. With a PC, you can get away with assuming that a malloc will succeed (although of course you shouldn't) but a micro controller is a very different beast.
And as for variables that are only needed during part of the execution & not all the fuctions , I used allocated shared scratch memory.
I’m not so interested to test this myself (I’m not well at the moment), but I see a lot of to-ing and fro-ing on the merits and failings of Strings w.r.t. memory use and code size.
I’d be really interested to see a comparison of Strings vs c-strings in code that is mixed process / String handling - when compared for execution speed.
The moving and reprocessing of String buffers must eat into COU time to some degree.
This rarely comes into the conversation, and in many cases is not important, but there are definitely cases where wasted CPU cycles would be a real issue.
Examples that come to mind would be reading fast quad-encoders, or real-time FFT, and similar algorithms.
There are certainly low performance applications where String memory and execution speed make no difference, or well placed String usage makes no difference, but a 1:1 face-off would interesting to see. (aka Py vs C )
If you use reserve() so that the Strings to not call malloc( ) then not a lot of difference since String use c-string methods underneath. There are extra method calls to check input args and available space to prevent null pointer and buffer overflow crashes, but that is about it.
If the method calls are 'wasting' too much CPU, then look at ASM to avoid the unnecessary push/pops of all the registers that are generated by the compiler.
(well were generated last time I tried to use C on an Attiny85)
Code size Strings definitely use more, but you get the protection you pay for.
I "de-sullied", rather rewrote my program. 0 String Objects, only global characters. I also removed a coupla bells and whistles. I re-used the SoftwareSerial at 9600 Bauds though to find out what the Hell is going on via the serial monitor (if needed).
Program Memory usage: 45%, RAM 74%(526 bytes free), freeMemory() shows 451 bytes.
Code has been running without a hiccup for a good spell now.
My conclusions (for myself at least):
- Avoid Strings like the Covid19. Don't let your software control your memory allocations and de-allocations.
- Don't be too ambitious to do a load of tasks with the memory-poor ATmega 328P. Leave sufficient memory margin to avoid spurious bugs that bite you in the ass a few hours/days later.
- Use a more powerful processor for the big jobs. I uploaded my original hungry-for-memory program on a Mega 2560 Pro. Needless to say, it works fine at the expense of the added price tag and its larger footprint (5.5x4cm) compared to a Nano.
The Rookie uses Strings because they seem easy, helpful and harmless. Now you know better - glad you got it working.
With that level of free RAM Strings can be problematic without careful usage (but still safe against sketch crashes).
I would recommend my SafeString library as a replacement.
It provides the safety and convenience of String type methods and buffer overflow protection while working on fix sized char[ ]s and providing detailed error messages so you can refine you char[ ]s down to the minimum size needed so saving precious RAM
You can also just 'wrap' a char[ ] in a SafeString for a few operations as needed.
If it runs and OP has been careful there is no need to wrap in anything
If he is unsure that would give him Warning messages to help identify issues but the memory footprint will increase due to your library so challenges might appear just due to this (may be not with that much free SRAM)
Thanx but I've changed religion. I don't believe in Strings anymore. Ah, but maybe I'll look into it for some of my previous Stringy sketches if it's easier to switch to SafeString rather than rewrite the code. Good idea!
Well, I have comptely solved my memory problem, and hence, intermettint crashes after delayed intervals thanks to removal of all Strings and using fixed allocations for all the character arrays that replace them. Things have been running for over a month for both of my modules which were crashing using Strings. I have 2 addirional sensor modules connected to these 2 modules via internet and Lora modulation radio transmission. The sensors measure outside temperature and humidity, and swimming pool water temperature and level. My next problem is the reliability of my HC-SR04 ultrasonic distance measurement device to monitor water level. After a few months, the device is damaged and rusted due to the proximity of the water (10cm). I would like to replace it by a sealed utrasonic device but have only succeded in finding one that works with distances>25cm. 5V Module de Capteur Ultrasonique Etanche pour Mesure Difficile et Humide : Amazon.fr: Bricolage. Anybody have an idea where I can find one that can mesure 7cm<distances<15cm? Thanks!!!!
good job getting rid of the instability
you might want to look at ToF sensors like the VL53L0X
(Assuming you read French since your Amazon link is in French) if you dig into the French section of the forum there were a few post discussing techniques for measuring water level.
thanx but tried it. laser will reflect on the bottom of the swimming pool, not on the surface. ideal for me is ultrason but sealed and minimum distance of about 7 cm. my sonde is installed 10 cm above the average distance of the water surface
you have very clear water ! (or very shallow)
if you put the sensor in a pipe/tube that is going down into the pool you could have a floating piece of polystyrene at the bottom that would serve as reflector. The pipe would add protection for your sensor.
Water is clear and about 1m80 deep. You can see the bottom so the laser too. Ultrason works great!
The sensor is in he red box. A pipe would have to be narrow as I have to remove the filter and basket for cleaning. But can't be too narrow to avoid unneeded echos against the walls. Ideal would be an ultrason sensor compatible wirh the same box but sealed.
you could get rid of the pipe and just have a vertical solid wire holding the "floater" in position under the ToF sensor.the "floater" would be free to move along the vertical wire with water level
Hey, that's a good one! I'll keep that suggestion in mind if I don't find a sealed ultrasonic sensor that I can just plug into my existing setup. Thanx for the idea!!!!
Found this today. Anyone have any experience with it? Thanx!