Project compile size producing unexpected size.

Hello All. I'm currently working on a project on a Nano that uses an OLED 128x32 screen, RTC and SHT21 Temp sensor.

All compiled fine well below the 30720bytes until I added code to switch between time and temperature.
The loop runs 2 functions: checkButtons and checkPane.

Compiled size without these 2 functions: 11236bytes
Compiled size with just checkButtons: 11508bytes
Compiled size with just checkPane: 24750bytes

So I would have expected a compiled size of around 25022bytes however it compiles at 34960bytes.

It appears to be the check buttons function. It increments a global variable upon pressing a button:

paneSelect = (paneSelect + 1) % PANE_END;

However if I use a local variable it compiles at 24780bytes.

Is it a bug in the compiler?

No, it's a bug in your code....

Regards,
Ray L.

tofuman:
Is it a bug in the compiler?

Almost certainly not.

Huge numbers of people use the compiler so 99.99% of the bugs were found long ago.

A more likely reason for your problem is that you are using a library with a bug in it.

But, as you have not posted your code ....

...R

Hi guys, thanks for your replies. I've stripped down the code (removing the splash screen). Which compiles as 20300Bytes. If I comment out the checkButtons function in the main loop it compiles as 14806bytes. Here is the code:

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <Sodaq_SHT2x.h>
#include <Sodaq_DS3231.h>

#define PANE_TIME     0
#define PANE_TEMP     1
#define PANE_END      2

char counter = 0;
char paneSelect = PANE_TIME;

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C oled(U8G2_R0);

void setup() {
  oled.begin();
  Wire.begin();
  rtc.begin();

  pinMode(12, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
}

void loop() {
  oled.clearBuffer();

  checkButtons();
  checkPane();
  
  oled.sendBuffer();
  delay(1000);
}

void checkButtons()
{
  if(digitalRead(12) == LOW)
  {
    paneSelect = (paneSelect + 1) % PANE_END;
  }

  if(digitalRead(11) == LOW)
  {
    paneSelect = paneSelect - 1;
      if(paneSelect < 0) paneSelect = PANE_END - 1;
  }
}

void checkPane()
{
  char tempStr[10];
  oled.setFont(u8g2_font_logisoso30_tf);
  switch(paneSelect)
  {
    case PANE_TIME:
    {
      DateTime Clock = rtc.now();
      sprintf(tempStr, "%02d", Clock.hour());
      oled.drawStr(20, 31, tempStr);
      sprintf(tempStr, "%02d", Clock.minute());
      oled.drawStr(69, 31, tempStr);
      if(counter % 2)
      {
        oled.drawStr(56, 31, ":");
      }
    }
    break;
    case PANE_TEMP:
    {
      int temp = 0, hum = 0;
      temp = SHT2x.GetTemperature();
      hum = SHT2x.GetHumidity();
      sprintf(tempStr, "%d C", temp);
      oled.drawStr(30, 31, tempStr);
      oled.drawStr(74, 36, "\xb0");
      oled.setFont(u8g2_font_crox3h_tf);
      sprintf(tempStr, "%d", hum);
      oled.drawStr(0, 32, tempStr);
      oled.setFont(u8g2_font_glasstown_nbp_tr);
      oled.drawStr(0, 18, "HUM");
    }
    break;
    default:
      return;
  }
  counter = (counter + 1) % 30;
}

If I change checkButtons to:

void checkButtons()
{
  if(digitalRead(12) == LOW)
  {
    paneSelect = 0;
  }

  if(digitalRead(11) == LOW)
  {
    paneSelect =0;
  }
}

It compiles as 20266bytes so it would appear to me that its setting the global value that is increasing the compiled size dramatically.

Thanks in advance.

I wonder is the modulus operator the culprit?

...R

After working with it today. The largest memory usage is due to the fonts so wanted to see if I could reduce that. I was using 3 fonts which were using 3k~ each. So I've created my own font which has reduced my compiled project from 34k to 18k. Although this doesn't address the issue that causes the memory usage to jump up around 4k when altering the global values (If I compile now without altering the global values it compiles at 15k). Even its just setting them to 0, taking modular division out of the code. I wonder if arduino is allocating 4096bytes for this regardless of the complexity, which is why the memory usage is jumping up so much... who knows.

Thanks for everyone's time.

It is the link time optimizer.
When it detects that paneSelect is always PANE_TIME, it removes unused code and data corresponding to case PANE_TEMP. This includes two fonts that take about 4 kilobytes.

Ah that makes sense now. I'm used to programming in C for PC without the need to worry about these size constraints. Thanks for the information.