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
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!

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.