#include library uses RAM

Hi,
why when I'm including library dynamic memory is being used ?
I'm not creating instance of object yet - just using #include

I'm making a test where I comment out include library sketch is using 44% of ram - when I want to use lib it takes 64%

Shouldn't ram be reserved when I will declare object ?

If only we could see some proof, and re-create the experiment {sigh}

What library?

Where is the code that causes this behavior?

These are all libraries which I wrote - but here is quick example:

//#include <Keypad.h>
//#include <Alarm.h>
//#include <AlarmKeypad.h>
//#include <AlarmSettings.h>
//#include <TextReceiver.h>
//#include <TextSender.h>
//#include <Notification.h>
//#include <NotificationPublisher.h>

result : Global variables use 3,656 bytes (44%) of dynamic memory, leaving 4,536 bytes for local variables. Maximum is 8,192 bytes.

lets uncomment

#include <Alarm.h>

and result is
Global variables use 5,260 bytes (64%) of dynamic memory, leaving 2,932 bytes for local variables. Maximum is 8,192 bytes.

Is there something what I could do wrong in library definition what cause that behavior ?

And most interesting thing is:
why even when I comment almost all content of Alarm h and cpp it still showing usage like 62% so just 2 % less.

But when completely remove alarm.h from import its back to 44% of usage

lonas:
And most interesting thing is:
why even when I comment almost all content of Alarm h and cpp it still showing usage like 62% so just 2 % less.

But when completely remove alarm.h from import its back to 44% of usage

You can't expect any help here if you don't show your library files.

Shouldn't ram be reserved when I will declare object ?

Only ram for that instance of the object is allocated when the instance is created. The class may require other data space.

Mark

I had all classes related with Alarm under one package/directory - when I have moved each class to separate folders then commented code in alarm class showed me again 44% usage.

Here is some next test:

  1. I'm importing just Alarm.h
  2. In alarm class all I do is import move sensor class which giving me usage from 44 to 46%
#ifndef MoveSensor_h
  #define MoveSensor_h

  #include <Arduino.h>
  #include <CommonConfiguration.h>
  #include <MemoryVariables.h>

  class MoveSensor
  {
    public:
      MoveSensor(byte arduinoId, byte pin, byte actionId, byte actionTypeId = LOCAL_ACTION, byte floorId = GROUND_FLOOR, byte enabled = LOW);
      void init();
      byte getArduinoId();
      byte getActionId();
      bool isGroundFloor();
      bool isFloor();
      bool isMoveDetected();
      bool isAlarmMoveDetected();
      byte getActionTypeId();
      void setEnabled(byte state);

    private:
      MemoryVariables memoryVariables;
      byte arduinoId;
      byte pin;
      byte actionId;
      byte actionTypeId;
      byte floorId;
      byte enabled;
      byte lastAlarmStateDetected = 0;
      word highAlarmStateTime = 0;
      byte lastStateDetected = 0;
      long changeTime = 0;
      int movementFloodCounter = 0;
  };

#endif
  1. when I comment out from move sensor #include <MemoryVariables.h>
    then usage is 42%

I dont know what is going on here...

In the spirit of "teaching you how to fish," there is a utility that you can use to create a map file which will show you what variables are being assigned to your memory.

  1. Go to your "Arduino\hardware\tools\avr\bin" directory and find "avr-objdump.exe".
  2. Go to the temporary directory when Arduino builds your code. It will be in a subdirectory created in "C:\Users\username\AppData\Local\Temp" that contains both "build" and ".tmp". You're going to want to find the .elf file in this directory.
  3. Type the command "avr-objdump.exe -t elf_file_name.elf >> map_file_name.map"

If you create map files with your library not included, included, partially commented out, etc you can then compare them to see what additional memory was used in each case. If you don't already use a code-compare tool I recommend downloading one immediately (WinMerge is free, small, and very popular).

Steps 1-3 can get pretty annoying to do manually so I made a python script to do it for me. Here it is if you know how to run python scripts:

import os, subprocess

def sorted_ls(path):
    mtime = lambda f: os.stat(os.path.join(path, f)).st_mtime
    return list(sorted(os.listdir(path), key=mtime))

home_temp_dir = os.path.expanduser("~") + os.sep + 'AppData' + os.sep + 'Local' + os.sep + 'Temp'

last_build_dir = ''
for dir_item in reversed(sorted_ls(home_temp_dir)):
    if((dir_item.find('build') >= 0 ) and (dir_item.find('.tmp') >= 0) ) :
        last_build_dir = dir_item
        break

if last_build_dir != '' :
    elf_filename = ''
    for dir_item in reversed(sorted_ls(home_temp_dir + os.sep + last_build_dir)):
        if(dir_item.find('.elf') >= 0) :
            elf_filename = dir_item
            break

if elf_filename != '' :
    print last_build_dir
    print elf_filename 
    subprocess.call('avr-objdump.exe' + ' -S -s ' + home_temp_dir + os.sep + last_build_dir + os.sep + elf_filename + ' > ' + elf_filename[0:-3] + 'lst', shell=True)
    subprocess.call('avr-objdump.exe' + ' -t ' + home_temp_dir + os.sep + last_build_dir + os.sep + elf_filename + ' > ' + elf_filename[0:-3] + 'map', shell=True)

Is there any linux version for that what You mentioned ?

Each library which I will comment out makes more memory space
comment out // #include <AlarmSettings.h> from Alarm.h makes 4% of space difference

Here is AlarmSettings.h

#ifndef AlarmSettings_h
	#define AlarmSettings_h

  #include <Arduino.h>
  #include <EEPROM.h>
  #include <MemoryVariables.h>
  #include <Notification.h>
  #include <Action.h>
  #include <OpenWindowDetector.h>

  class AlarmSettings
	{
		public:
      void initWith(Notification *notification, Action *alarmSetting);
      void addOpenWindowDetector(OpenWindowDetector *openWindowDetector);
      void handle();
      bool processSetting(String setting);
      bool isAlarmArmed();
      void armAlarm();
      void disarmAlarm();
      bool isGroundAlarmArmed();
      void armGroundAlarm();
      void disArmGroundAlarm();
      bool isFloorAlarmArmed();
      void armFloorAlarm();
      void disArmFloorAlarm();
      bool isAlarmFreezed();
      void longTemporaryDisarmAlarm();
      void shortTemporaryDisarmAlarm();
      byte getFreezeTime();
      void removeTemporaryDisarmAlarm();
      void setAutoArmForGroundAlarmEnabledTo(byte state);

    private:
      MemoryVariables memoryVariables;
      Notification *notification;
      Action *alarmSetting;
      OpenWindowDetector *openWindowDetector;
      byte isAutoArmForGroundAlarmEnabled = ENABLED;
	};

#endif

lonas:
Is there any linux version for that what You mentioned ?

There certainly is, although I do not have a Linux installation of the Arduino IDE to tell you where they put the file. Search the directory where you have the Arduino IDE installed for "avr-objdump.exe."

I'm also not sure what temporary directory the Arduino IDE would use for building in Linux, but you should be able to tell when you build the code. Go to File->Preferences and then click the checkbox to "Show verbose output during: compilation." The next time you build, you'll see all of the commands run as your project builds. In those commands, you should be able to see a weird temporary directory that Arduino created when it built your project.

If you're getting to the point where you're wondering which of your code is consuming which resources, learning how to make a map file will be a very powerful tool.

As for comparing two map files, WinMerge is a Windows only program. There must be many similar programs for Linux, however. They list some here -> 14.04 - Best alternative for WinMerge - Ask Ubuntu

All right - I have tracked it down to some particular example:

Including in main sketch button library which takes me 10% of memory - without object initialization..

#include <Button.h>

which looks like:

#ifndef Button_h
	#define Button_h

	#include <Arduino.h>
  //#include <CommonConfiguration.h>

	class Button
  {
    public:
      Button(byte arduinoId, byte pin, byte shortPressActionId, byte buttonActionTypeId = 1, byte buttonTypeId = 1, byte holdPressActionId = 1, byte doublePressActionId = 1, byte relatedButtonActionId = 1);
      void init();
      byte getArduinoId();
      unsigned int getActionId();
      byte getRelatedActionId();
      byte getButtonTypeId();
      byte getButtonActionTypeId();

      unsigned int getPressedActionId();

    private:
      byte arduinoId;
      byte pin;
      byte buttonTypeId;
      byte buttonActionTypeId;
      byte shortPressActionId;
      byte holdPressActionId;
      byte doublePressActionId;
      byte relatedButtonActionId;
    
      bool   buttonState;
      bool   buttonPreviousState;
      bool   shouldWaitForDoublePress;
      bool   registerDoublePress;
      bool   singleOK;  // whether it's OK to do a single click
      long   pressTime;
      long   releaseTime;
      bool   shouldIgnoreButtonReleaseBecauseOfHold;
      bool   waitForUp;        // when held, whether to wait for the up event
      bool   holdEventPast;    // whether or not the hold event happened already

      byte readEvent();
      bool isPress();
      void setPressAttributes();
      bool isRelease();
      bool isDoublePress();
      void setDoublePressAttributes();
      bool wasPress(int event);
      bool wasHold();
      void setHoldAttributes();
      bool wasLongHold();
      bool hasSecondCommand();
  };

#endif

RE READ POST #6 Your basic understanding of what is going on is complete CRAP

Mark

Instance

holmes4:
Only ram for that instance of the object is allocated when the instance is created. The class may require other data space.

Mark

that is not creating instance of object

 #include <Button.h>

that does

  Button(ARDUINO_2, A8, BATH_ROOM_GROUND, LOCAL_ACTION, BUTTON, BATH_ROOM_GROUND_SHOWER),

so I dont get what You mean...

All right I have found root cause of that behavior but if some one could explain me why its happening.

I have couple of entity classes under one library directory, like button, relay, move sensor (7 classes)

When I have moved button class to separate package/folder then include of button takes 0% of usage when moved back to entity package it takes 10%

why.. ?

The linker is a femme fatale in GCC's clothing.

Want a better answer? Post source code with instructions that demonstrates the problem.

All right so lets do really simple experiment:

#ifndef Logger_h
	#define Logger_h

  #include <Arduino.h>
  //#include <MemoryVariables.h>
  //#include <MQTTClient.h>

	class Logger
	{
		public:
      //void initWith(MQTTClient *mqttClient);
      void debugF(const __FlashStringHelper* log);
      void debugS(String log);
      void debugC(char* log);

		private:
		//  MQTTClient *mqttClient;
		  //MemoryVariables memoryVariables;
		  bool isDebugEnable();
	};

#endif

cpp

#include "Logger.h"


//void Logger::initWith(MQTTClient *mqttClient)
//{
  //this->mqttClient = mqttClient;
//}

void Logger::debugF(const __FlashStringHelper* log)
{
  if (isDebugEnable())
  {
    char arduinoName[20];
    //strcpy_P(arduinoName, (char*)pgm_read_word(&(ARDUINO_NAMES[memoryVariables.getArduinoId()])));

    Serial.print(arduinoName);
    Serial.print(" ");
    Serial.println(log);
  }
}


void Logger::debugS(String log)
{
  if (isDebugEnable())
  {
    char arduinoName[20];
    //strcpy_P(arduinoName, (char*)pgm_read_word(&(ARDUINO_NAMES[memoryVariables.getArduinoId()])));

    Serial.print(arduinoName);
    Serial.print(" ");
    Serial.println(log);
  }
}

void Logger::debugC(char* log)
{
  if (isDebugEnable())
  {
    Serial.print("- ");
    Serial.println(log);
  }
}

bool Logger::isDebugEnable()
{
  return true;
  //return memoryVariables.isDebugEnable();
}

import that library in new sketch

#include <Logger.h>

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

and now when I will return in isDebugEnable true complier shows 2% of dynamic memory used (182bytes)
when it set to false its 0 ....

who can explain me why??

Well, Serial is going to take two lots of 64 bytes for the input and output buffers, plus the strings. . . .

Expanding on @AWOL's answer...

Serial uses interrupts. By using interrupts, the linker is forced to bring part of Serial into the image even though Serial is not actually used by your sketch.

When isDebugEnable returns false the compiler (optimizer) determines that all your code referencing Serial is unreachable (dead) so the compiler eliminates that part of your code.