Here's an example of a class which crashes the ESP8266-03 causing it to reset:
Test.hpp file:
#include <map>
class Test {
public:
int data() const;
Test(int x);
~Test();
protected:
int _data;
static std::map<int, Test const *>thing;
static void _Reserve(Test const * const t);
};
Test.cpp file:
std::map<int, Test const *> Test::thing;
int Test::data() const
{
return this->_data;
}
void Test::_Reserve(Test const * const t) {
Test::thing[t->data()] = t; // Works fine if this line is removed.
}
Test::Test(int x): _data(x)
{
Test::_Reserve(this);
}
Test::~Test() {};
Project.ino:
#include "ESP8266WiFi.h"
#include "Test.hpp"
Test test(2);
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.print("Timer: ");
Serial.println(millis());
delay(1000);
}
The following does NOT crash the ESP8266-03 and prints the time as it should:
#include "ESP8266WiFi.h"
#include <map>
class Test {
public:
int data() const
{
return this->_data;
}
Test(int x): _data(x)
{
Test::_Reserve(this);
}
~Test() {};
protected:
int _data;
static std::map<int, Test const *>thing;
static bool _Reserve(Test const * const t) {
Test::thing[t->data()] = t;
}
};
std::map<int, Test const *> Test::thing;
Test test(2);
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.print("Timer: ");
Serial.println(millis());
delay(1000);
}
When the first version is uploaded to the board, I get the following in the serial monitor:
ets Jan 8 2013,rst cause:1, boot mode:(1,7)
ets Jan 8 2013,rst cause:4, boot mode:(1,7)
wdt reset
When I reset it and boot it regularly, no upload mode, the following repeats every ~1 second:
ets Jan 8 2013,rst cause:1, boot mode:(3,7)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v09f0c112
~ld
-
Does accessing a static POD variable cause the same issue?Code Gorilla– Code Gorilla2017年01月10日 08:40:32 +00:00Commented Jan 10, 2017 at 8:40
-
@Matt I believe I haven't tried that, but will check later on today. It's a bit strange since removing that line with a comment works fine. I can even add the same line to another method in the class (such as a new setData method, in that example up there) and it works properly... If I make the variable public, I can access it properly as well from outside the class. It probably has something to do with the constructor.MayBee– MayBee2017年01月10日 10:40:16 +00:00Commented Jan 10, 2017 at 10:40
1 Answer 1
Why does static member std::map reset ESP8266 when outside the .ino file?
What happens if the Test() constructor is run before the map constructor? This is the problem: you are assuming order of execution.
Use a Singleton pattern or init() member function to force the ordering that is required.
Cheers!
-
Like you said, it was an initialization issue. Turns out the Test instance in the first example is considered static, making it run before std::map is initialized since it's static code is in another translation unit (another file), but I think this comment better explains the reason for the problem: stackoverflow.com/a/26996015/3342154MayBee– MayBee2017年01月10日 20:58:37 +00:00Commented Jan 10, 2017 at 20:58
Explore related questions
See similar questions with these tags.