"Global variables use..." seems wrong

The 2.0.2 IDE says I'm using 391 bytes of global variables. This number does not seem to change ... ever. I can freely add initialized or uninitialized public or public static variables and it always says I'm using 391 bytes of global variables. I should add that the 1.8.19 and also 1.8.15 IDEs give the same result. I will also note that this question has been raised before with no answer or solution given. I imagine this is a misunderstanding on my part, but can someone help me understand it?

An example is below. The entire sketch is on Github.

#include "task_decls.h"
#include "port_decls.h"
#include "display_decls.h"
#include "led_decls.h"
#include "log_decls.h"

#include "heartbeat_task.h"
#include "serial_task.h"
#include "port_task.h"
#include "display_task.h"
#include "led_task.h"
#include "log_task.h"

#include "task_runner.h"

// Comment out the next line or not, and the IDE still gives the message "Global variables use 391 bytes (19%) of dynamic memory, leaving 1657 bytes for local variables. Maximum is 2048 bytes."
char* foo = "This is a long string. It's got enough bytes that the number of bytes in use should definitely change. In fact I'm going to make it even longer so there's no doubt. Done.";

void setup() {
  InitTasks();
}

// Main body - delegate to task runner
void loop() {
  for (;;) {
    RunTasks();
  }
}

Welcome

Is foo used somewhere in your code ? If not, it is removed from your code by the compiler

Thank you. The actual example I hit in my code was not this naive but unfortunately it's too long to post. It involves a global variable that is referenced from a function that is only called through a table of function pointers.

Well, here's a stab at it:

  typedef State (*CommandHandler)(RING *const r, byte b);

// stuff removed

typedef struct pollBuffer {
    int unsent;
    byte buf[259];
  } PollBuffer;

  PollBuffer uniquePollBuffer;
  constexpr byte GUARD_BYTE = 0xAA;

  PollBuffer* const pb = &uniquePollBuffer;

  void allocPollBuffer() {
    if (pb != 0) {
      panic(PANIC_SERIAL_NUMBERED, 0xA); 
    }
    pb->unsent = 0;
    pb->buf[258] = GUARD_BYTE;
  }

  void freePollBuffer() {
    if (pb->buf[258] != GUARD_BYTE) {
      panic(PANIC_SERIAL_NUMBERED, 0xB);
    }
  }

  State stPoll(RING* const r, byte b) {
    allocPollBuffer();
    freePollBuffer();
  }

// stuff removed

  const PROGMEM CommandHandler handlers[] = {
    stBadCmd,   stBadCmd,  stBadCmd,   stBadCmd,     // 0xE0 ...
    stBadCmd,   stBadCmd,  stBadCmd,   stBadCmd,     // 0xE4 ...
    stBadCmd,   stPoll,    stBadCmd,   stBadCmd,     // 0xE8 ...
    stBadCmd,   stBadCmd,  stGetVer,   stSync,       // 0xEC ...
  
    stBadCmd,   stBadCmd,  stBadCmd,   stBadCmd,     // 0xF0 ...
    stBadCmd,   stBadCmd,  stBadCmd,   stBadCmd,     // 0xF4 ...
    stBadCmd,   stBadCmd,  stBadCmd,   stSetK,       // 0xF8 ...
    stBadCmd,   stBadCmd,  stBadCmd,   stBadCmd,     // 0xFC ...
  };

I don't see anywhere that "handlers" is used. If that gets optimized away, so does stPoll().

I don't know if the compiler is smart enough to notice that you only use one byte of 'buf'. :slight_smile:

Thank you John. At some point the compiler decided the variable was "used" and the value did increase. I just have a little faith. Also thank you @guix.