Library variable gets reset / is not saved

Hello,

I ran into a problem I simply couldn't figure out, and as a test I boiled down the project to the absolute simplest form and I am still seeing the problem:

I take a variable passed when the library is initialized and store it as a private variable. When I try to call the private variable from a function in the library, the variable has been reset to 0. This seems to happen with public variables as well, unless they are set from outside the library.

I am using Codebender--is this some sort of bug on their part, or am I missing something? It seems so simple! The following are my test files:

Test.ino

#include "test.h";

test test1(3);

void setup()
{
	Serial.begin(9600);
}
void loop()
{
	test1.printVar();
	while(true){
	delay(1000);	
	}
}

Test.h

#ifndef test_h
#define test_h

#include "Arduino.h"

class test
{
  public:
    test(int var);
	void printVar();
  private:
    int _var;
};

#endif

Test.cpp

#include "Arduino.h";
#include "test.h";

test::test(int var)
{
	int _var = var;
	Serial.print(_var);
}
void test::printVar(){
	Serial.print(_var);
}

The variable is passed from the .ino to the .cpp and stored as _test. Printing it out gives "3" as expected. Then, from the .ino I call the function printVal, and you would expect "3" to be printed out again, but it prints "0".

All examples I've seen seem to say this should work. What am I missing?

Thanks!

Don't rely on a constructor for initialising your class instance. I know it's the correct way to do it in other environments but it's not reliable on an arduino. This is why things like Serial etc.. use a separate function called begin.

It's one of those subjects I've been meaning to research because I don't quite understand why. I just know that the constructor cannot be assumed to run as you'd expect.

Interesting. Even the official Arduino tutorial on writing libraries says to do it this way. Using a separate function to set up all the variables does sound like a valid work-around. Hacky, but I can do it that way.

Thanks for the quick feedback!

Using things that rely on hardware initialization is not safe in the constructor. Setting a variable is perfectly fine. Your problem is that you aren't using the private member variable you created. You are creating a new local variable inside the constructor and setting it. As soon as the constructor returns that variable goes out of scope and is destroyed.

Lose the int in the first line.

test::test(int var)
{
	int _var = var;
	Serial.print(_var);
}

Should be:

test::test(int var)
{
	_var = var;
	Serial.print(_var);
}

However, the Serial.print line in the constructor does rely on the hardware being initialized. That line might break things. But it isn't the reason your variable isn't being set.

Delta_G:
You are creating a new local variable inside the constructor and setting it.

Aha! I could have sworn I tried leaving out the int was given a compiler error saying it needs a type. I must have confused it with something else (header file, maybe).

Thanks for pointing out the obvious, I knew it would be a simple answer :smiley:

Delta_G:
Lose the int in the first line.

Agh, can't believe I missed that :slight_smile:

Delta_G:
Using things that rely on hardware initialization is not safe in the constructor. Setting a variable is perfectly fine.

And thanks for clearing that up. :slight_smile: