Strings Revisited

I am clearly not an experienced Arduino user or programmer but I'd like to clarify something for 2021: Is it finally okay or not to use Arduino String()? I've read at least a dozen posts from users, presumably much more experienced than I, who bemoan the usage of String and instead often advocate for char. One user even stated that String was added to the Arduino library as a "crutch" for beginners because it is easy to use. Some of these posts go back to 2014 so I am wondering if this is a dead issue or still very much alive, but not in the George Romero sense of "alive."

Which brings me to my problem: Several function calls in the ArduinoBLE library return String results, such as peripheral.address(), localName(), advertisedServiceUuid(), etc. This seems to be a paradox although perhaps The Builders of the library had nothing but good intentions and warm feelings regarding String and were not the actual longer-term users who had to deal with the fallout, like Linda Hamilton in the first Terminator movie.

My problem is that I've added plenty of other String features in the form of tables which, admittedly, are easy to construct and hold all the other String-based objects that are part of BLE profiles, including the data from characteristics and descriptors. Although I have not determined the cause exactly, I have observed certain changes affect my Arduino Nano 33 IoT's performance.

For example, if I quadruple the size of my tables (although I don't allocate the String size I allocate how many Strings -- rows, really -- I will hold) I see that the compiler shows 72% dynamic memory usage and my Arduino will no longer program because somehow my program has stomped on the USB serial port. If I reduce this by 50%, I see that my program compiles, dynamic memory usage is 47%, the serial ports work and things are okay until I start running and collecting data, at which point after finding another BLE device and storing it something happens to the memory and my Arduino crashes (serial port stops responding, Arduino needs to be manually reset). My final experiment is to halve the table amount again and this time I get everything - successful compiles, dynamic memory at 28%, working serial ports and Arduinos that run for at least 24 hours and store 3 different profiles (which happen to be the number of peripherals I have on-hand).

I am the first to admit that I have not solved the real problem, which appears to be something related to my memory usage and serial port operation, and based on forum posts my heavy use of String especially in tables may have a corrupting influence. In any case, I think it would be good to put to rest once and for all if String is truly meant to cover the universe in darkness and hatred or if it is okay to use in 2021. If it is really bad, then maybe I should convert all my String-based tables to 2-D char arrays which might utilise better inherent memory management, and perhaps going forward, function returns are no longer built for Strings?

  • Fred

I think using strings on a larger more powerful 32-bit processor with more RAM is OK for limited use.

The main issue is not the year 2021 but the architecture of microcontrollers. Microcontrollers address physical memory directly and the amount is severely limited.

On PCs, mobile phones or a Raspberry Pi the processors have memory management units that are handled by the operating system. The MMU translates virtual addresses to physical addresses. If the OS runs out of RAM it can make use of additional memory system like hard drives and unload data from RAM and give the RAM to the currently running process. If you try to access memory that has been unloaded the OS is notified and it will put the data back into RAM.

This does not work with directly addressed memory. Dynamically allocating memory is more difficult. It can lead to fragmentation of the HEAP memory. Which in turn can lead to no RAM being available even if there are enough fragments of RAM in the HEAP. There is no way of virtually adding memory or rearranging the memory into one block.

While data that is known in size can simply be placed onto the stack. The stack will grow and shrink as needed leaving no holes in memory.

The disadvantage of MMU is that memory access become unpredictable. It can take a long time before the OS has found the data and placed it back in memory.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.