What I try to do is to pass a pointer to a PROGMEM char-array to a class. I want that the calls gets a "name" which is stored in PROGMEM. I want the class only to hold the pointer to the char-array in PROGMEM. I failed.
So I tried to narrow it down and it seems like whenever I try to copy the pointer to another variable I just read the wrong portion in the memory. I put together some sample code which exactly shows the unintenden behavior.
AquaMaster NT v0.1 is starting up ...
verboseTexts[1] pointer: 135
Read Try: String 1
************************************
testpointer: 135
Read Try: v⸮⸮⸮6⸮⸮⸮⸮/⸮⸮⸮#⸮⸮⸮⸮=⸮c⸮v⸮⸮⸮%⸮⸮⸮⸮⸮
As you can see the simple instruction const char* testpointer = verboseTexts[1]; seems to be wrong. I guess I cannot just copy since the pointers are stored in PROGMEM too. I tried already some things with pgm_read_ptr and similar but I never could get the same output.
Strange: If I try it on an NodeMCU Board with an ESP8266 this is working without issue. Seems like they do use some different memory-management there or whatever.
I tried two different Ardunio Mega 2560 since this is the hardware it should run - same behavior.
Really hope someone can tell me what is going oin there.
Thanks.
I read this. This ist why the first part successfully displayed the string from PROGMEM. However, as soon as I copy the const char pointer I read garbage. Even as if it looks like the content is the same. Or do I miss something on that example page?
That''s SUPPOSED to invoke the same println code that F("literalstring") would (except the F macro also contains code to put the literal string in flash, which won't work if there's already a pointer.)
testpointer is already a pointer to a progmem location, and strlcpy_P() expects the 2nd argument to be a pointer to progmem, so the (char*) and pgm_read_word are unnecessary.
strlcpy_P(buffer, testpointer, 50); //this works in your code - see explanation below
Note that this only works because the compiler sets the value of testpointer during compilation, testpointer is a constant value pointing to one specific location in progmem that the compiler knows the value of while compiling.
const char* testpointer = verboseTexts[1]; //<<<< this line will work properly
//these lines of code WILL NOT work properly, vecause verboseTexts[] is stored in progmem
// and testpointer has to be set during program execution, not during compilation.
char* testpointer;
testpointer = verboseTexts[random(5)];
//this will produce the expected results
char* testpointer;
testpointer = pgm_read_word(&verboseTexts[random(5)]);
The compiler optimizations can trick you with stuff like that when testing simple examples, the test code appears to work fine, but later on when you actually start setting values dynamically within the code you no longer get the expected results.
david_2018:
The compiler optimizations can trick you with stuff like that when testing simple examples, the test code appears to work fine, but later on when you actually start setting values dynamically within the code you no longer get the expected results.
The code posted in Reply #3 works and handles dynamic selection of the array element correctly.
What shall I tell you: It works. Many thanks. I already got suspicious about the simple assingment of testpointer. Like told I already tried to use the prgm_read...stuff and did not succed. What I was missing is simply the change in strcpy_P-function I always still used