1

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
asked Jan 10, 2017 at 8:02
2
  • Does accessing a static POD variable cause the same issue? Commented 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. Commented Jan 10, 2017 at 10:40

1 Answer 1

0

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!

answered Jan 10, 2017 at 14:37
1
  • 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/3342154 Commented Jan 10, 2017 at 20:58

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.