0

I'm trying to understand if a char * variable can be updated down the code (since it only stores a pointer) or over-flow can occur.

For example:

char *A="/file.txt";

char *B;

void print_filename(char *filename="/defname.txt"){
Serial.println(filename);

Is is the right way to use char* variable, so down the road I assing new values :

A="/anyOtherfile.txt";

B="This_is_not_empty";

print_filename("/logfile.txt");

1 Answer 1

3

No overflow can occur when using char pointers like you did in your question.

You use a number of different string literals (the strings enclosed by double quotes). These automatically get placed in RAM by the compiler, but they are not meant to be writable. When you do

char *A="/file.txt";

the compiler will place the literal in RAM (not in stack, but in the read-only section, even if the literal is used inside of a function (Thanks to Edgar Bonet for the comment)) and then set the pointer A to the address of that literal. Writing to that address is undefined in the C++ standard and should not be done.

When you then do something like this

A = "some other literal";

then you are not changing the literal. Instead you are just changing the pointer to a different literal placed in RAM. So no overflow can occur, since the compiler just takes all string literals, places them in RAM (immutable) and only handles their memory addresses. So there is no writable buffer in the first place.

With

void print_filename(char *filename="/defname.txt"){
Serial.println(filename);

you are setting the default value of the filename pointer to the address of that specific literal. Setting the parameter to an address of another literal or an existing char array will just change the pointer. If you at another pointer again set filenameto that exact literal, the literal still lies in RAM and the compiler will usage again its address (so multiple uses of the same literal will not result in higher memory use).

If you - at some point - want to write data to that pointer, you first need to set it to a char array, either the address of a static array or creating a new dynamically allocated array with the new keyword:

char my_static_array[10];
A = my_static_array;
// now you can write to the array my_static_array by using A
A = new char[15];
// now you can write to a newly created array by using A

Though for the dynamic allocation you need to keep in mind, that especially AVR based Arduinos (like the Uno/Nano/Mini) don't have much memory and often dynamically declaring and deleting memory can lead to memory fragmentation (essentially the delete operations free memory, but these holes with free memory are often too small for the next allocations, so they don't get used and your memory gets like swiss cheese). That is also the reason why using the Arduino String class in the wrong way is really bad.

4
  • So passing another string literal will not cause any overflow, since you are only passing the parameter, if I get it right ?
    – guyd
    Nov 11, 2022 at 11:14
  • 1
    It cannot cause overflow, because you only pass the pointer to an already existing string in memory. It doesn't get copied to another place
    – chrisl
    Nov 11, 2022 at 11:26
  • 1
    +1, Nice answer! But note that the string literals are not stored on the stack: they are statically allocated in the .data section of the program (or .rodata, for “read-only data”, if available on the platform). This is the case even if, in the source code, they appear within a function body. Nov 11, 2022 at 11:59
  • @EdgarBonet Ah, thanks. Thought it would be on the stack, now I learned otherwise. I will edit my answer to reflect that
    – chrisl
    Nov 11, 2022 at 13:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.