Declared Const value is changing! how??

I can't seem to find an answer for this anywhere, and its surprisingly difficult to do a search on ...

I have a project thats several thousand lines compiling to 18280 bytes (56%) using 1263 bytes for global variables (61%)

All on a 328p on a custom PCB.

The area i'm having problems has not changed in months - hardware or firmware), but suddenly started doing weird things after tweaking some things in unrelated functions.

Within one function that displays data on a screen, I have:

const byte _dataX = 53;
  const byte _dataY[] = {13, 26, 39, 63}; // Y value for screen lines

// These are later used in a for loop 

for (byte i = 0; i <= (RFNodes - 1); i++)
    {
      OLED.setCursor(0, _dataY[i]);     // Set cursor to prepare for write
      OLED.print((char *)rmName[i]);   // Print room name, char array

      OLED.setCursor(_dataX, _dataY[i]);  // Set cursor to prepare for write
      OLED.print(data[i]);                         // Print Data
      

      // other stuff that works fine
     }

When I added some unrelated code that tracks data cycles in a single byte (allowing it to roll over after 255), the value stored in/as _dataY[0] started matching that counting byte.

I took me a long time to track down what was happening, as I didn't think a const value could be changed.

I attempted a:

_dataY[0] = 13;

just to see what would happen, and I got the expected error:

exit status 1
assignment of read-only location '_dataY[0]'

The only thing I can think of is that I'm somehow using all my RAM space and the constant happens to be the address that is being overwritten ??

Is that possible? I'm not sure what the memory would do in that case.

The only way I was able to track down the problem was because the data supposed to be displayed was slowly stepping down the screen and I happened to notice it corresponded with the counter increments. (based on outside info coming in via interrupt, so it isn't regular)

Any ideas?

I can't see the full code helping here, as it's a fundamental level issue - Why is my declared 'Const' not acting as a constant??

I tried moving the declarations to a global level and everything is working again, so for the time being, I'll try freeing up more memory - I have to get better at not using globals anyway. :slight_smile:

But, if anyone can explain what's happening &/or a better solution, it would be appreciated.

Const means read-only, not compile-time constant. Often times, the object still lives in RAM, so it can be changed if your code misbehaves.

The things you are describing sound like the kind of undefined behavior that occurs when you go out of bounds on an array. UB anywhere in your code could be the culprit, but start looking close to where the error manifests itself. All pointer manipulations and array accesses are suspects. Illegal pointer conversions could be the reason as well.

You can check your memory usage using the MemoryFree library, but I don't think that's the issue here.

Pieter

PieterP:
...

The things you are describing sound like the kind of undefined behavior that occurs when you go out of bounds on an array. UB anywhere in your code could be the culprit, but start looking close to where the error manifests itself. All pointer manipulations and array accesses are suspects. Illegal pointer conversions could be the reason as well.

Thanks Pieter,

That may be it .. I was working on a different display function, for a menu, when the problem started.

It started somewhere inside this:

const char menuName[][12] = { // An array of char arrays to use for menu display function
    "Exit",               // F() Vs PROGMEM??
    "Control",
    "Brightness",
    "Calibration"};

const byte MAXmainMenuLevels = 4;



void menuMainDisplay(byte _selection){

  const byte dataX = 53;
  const byte dataY[] = {13, 26, 39, 52}; // Y value for screen lines
  const byte markerX = (dataX -20);     // X position for Active selection indicator - uses dataY[]

  OLED.firstPage();
  do
  {    // all graphics commands have to appear within this loop body.
    
    OLED.setFont(u8g2_font_6x13_mr); // Set a font for 9 Pixel high

    for (byte i = 0; i <= (MAXmainMenuLevels-1); i++)
    {
      OLED.setCursor(dataX, dataY[i]);     // Set cursor to prepare for write
      OLED.print((char *)menuName[i]);       
    }

  
    OLED.setCursor(markerX, dataY[_selection]); // Set cursor to prepare for write
    OLED.print(F("**"));
  } while (OLED.nextPage());

}

(The DataX & Y are not the same as the earlier code, these only exist within this function.)

If I replace the For loop with:

    OLED.setCursor(dataX, dataY[0]);     // Set cursor to prepare for write
    OLED.print((char *)menuName[0]);     
    OLED.setCursor(dataX, dataY[1]);     // Set cursor to prepare for write
    OLED.print((char *)menuName[1]);     
    OLED.setCursor(dataX, dataY[2]);     // Set cursor to prepare for write
    OLED.print((char *)menuName[2]);       
    OLED.setCursor(dataX, dataY[3]);     // Set cursor to prepare for write
    OLED.print((char *)menuName[3]);

it doesn't crash, even though they should be functionally the same, yes?

Now it just freezes up and eventually puts some garbage on the screen

I'm sure i'm missing something obvious, but I've been staring at it for so long, I can't see it :frowning:

Upon using a ton of serial debugging, I'm now thinking I may have a stack overflow issue, or something like that, in my menu system ...

I've got to a point where everything is working if I comment out a single line in the FOR loop:

OLED.print((char )menuName);*
However, if I replace that line with:

  • OLED.print("Line ");*
  • OLED.print(i);*
    I DO get a working display, just instead of the menu names I just get:
  • Line 0*
  • Line 1*
  • Line 2*
  • Line 3*

And that exact command worked when the menu was simpler.
therefore, I'm thinking the pointers are the 'last straw'
Does this seem like a reasonable conclusion?
What's the best way to free up space on the stack, if that's the case? I'm only within a few parent functions, it isn't 100's, or even 10's.

To free memory, put all constant data that never changes in PROGMEM(flash). It will increase the free memory that you can work with but it will not solve the problem if it's not a clash if heap and stack.

Note that undefined behaviour can be caused in one place but manifest itself in a totally different place.

I suggest that you post/attach your full code; somebody might be willing to check it.

As PieterP pointed out, check all your arrays for access outside the boundaries for starters.

Sunkmail:
I've got to a point where everything is working if I comment out a single line in the FOR loop:

   OLED.print((char *)menuName[i]);

I've been wondering why you have a cast there. Do you get a warning is you don't cast the character array to a character pointer?

sterretje:
To free memory, put all constant data that never changes in PROGMEM(flash). It will increase the free memory that you can work with but it will not solve the problem if it's not a clash if heap and stack.

Note that undefined behaviour can be caused in one place but manifest itself in a totally different place.

I suggest that you post/attach your full code; somebody might be willing to check it.

As PieterP pointed out, check all your arrays for access outside the boundaries for starters.

I already have everything that can use the F() macro using it, so I'm good there.

I suppose using #Define Vs const could help in this instance??

I've been looking at the arrays and they all seem fine, but will investigate further.

I did find something that helped - But it may just be masking the issue for the time being ...

I turned off the LTO setting.

It does increase the program memory usage up to around 64%, but that's not an issue - there isn't much more code needed.

Apparently somewhere in the optimization routine, the linker is doing something less than ideal.

I may still be very close to a stack collision, so I'll try other ideas to minimise the the future risk.

johnwasser:
I've been wondering why you have a cast there. Do you get a warning is you don't cast the character array to a character pointer?

Honestly, I think I just used the example I found with the library and it worked, so I didn't touch it.
I'm don't have the code handy at the moment, but I think it's the ug82 library?

I'm still having trouble getting my head to accept pointers. I understand the concept, but I have difficulty with implementation. Therefore, generally avoid them, unless I have some sort of tutorial to follow.

I first learned firmware programming in the mid/late 90's, then didn't use it until getting back into electronics and starting a couple of small projects a few years back. I'm still playing catch-up.

Unfortunately, I lost contact with all my engineering people when I changed careers about 15 years ago, so I don't have any mentor types I can ask - Other than the forums.

I even tried switching to a different IDE in an attempt to understand the inner workings better, but I seem to not quite be there yet.
I did well figuring it out until I had to step away for a couple of months. By then I had forgotten how to do some basic things, so figured I come back to the arduino one.
(Still wishing for a way to step through the code - is there some sort of HW emulator out there somewhere? Using the serial port is a bit too limiting when trying to follow several variables :stuck_out_tongue: )

This is still very much a small hobby that I have limited time to devote towards.

How should we know; you only posted snippets.

It's not only the F macro. Things like below can go in PROGMEM as well.

const char menuName[][12] =
...
...

Read up on how to do it (it's not the F macro).