What would be the best-practice in this kind of situation?
To not use String
.
I also want to allow the end user to use the String functions (like indexOf) to search for particular content in emails.
There's nothing wrong with providing an indexOf
function in your API. But you don't have to use String
to implement that function when called. You can just use the strstr
function on char arrays (reference here).
I should also point out that most Arduinos do not have enough RAM for storing an email.
UPDATE 07-01-2016:
To answer the titular question, the fixed cost of using String
is at least 1600 bytes of program space, more if you use more than a few methods. The linker can throw out methods you don't use.
Then for each String
variable you declare, the recurring cost is 8 bytes for the variable itself, plus the variable-size memory chunk for your character data. This chunk is allocated from the heap, and is the size of your string plus 4 more bytes to manage the chunk within the heap. That's a total of 12 extra bytes per String
instance.
However, I did not originally answer that question because you explicitly asked about the memory expense. This ignores other expenses that should not be ignored:
- execution time - Allocating memory from the heap is really a search for a chunk of the requested size. At the beginning it can be quick, but as the heap gets fragmented (small chunks build up) it takes longer to find a chunk. And when the
String
is emptied or destroyed, the memory chunk gets put back into the heap and (possibly) merged with adjacent chunks. Reducing the size of a String
does not free up any memory. The String
maintains its maximum size until it is emptied or destroyed.
- long-term stability - Embedded Systems are supposed run forever. A primary characteristic of a system that can run forever is "deterministic." For whatever inputs it receives, it has a predictable response and end state. When you use the heap via
String
, the heap gets fragmented according to the data it handles. This is not predictable, and it may get into a state where no memory chunk of the requested size is available. Choke.
- maintenance - because the heap state depends on the processed
String
data, finding the cause of the failure can be difficult. It can fail at different times because the input data is different, and it can fail at different places in the program.
Because of these expenses, String
is rarely used by an experienced developer. Unfortunately, String
is tempting to the beginner because it is easy to understand. What is difficult to understand is the complicated, non-deterministic behaviour under the hood that inevitably leads to system failure, rending of garments and gnashing of teeth.