В PubSubClient не так много субтитров, просто (imo) плохая документация и неоптимальный API.
Конструктор PubSubClient получает ссылку на клиента.
PubSubClient(IPAddress, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client);
И затем получает указательсохранить его как член.
Это означает, что он ожидает экземпляр Client
, на который он ссылается, чтобы пережить экземпляр PubSubClient
.
Сбор мусора не происходит.Просто если вы объявите объект с автоматической продолжительностью хранения, то он будет уничтожен, когда выйдет из области видимости.
Так что причина по сути такова:
struct B{
int num;
};
struct A{
A(B& param){
m_b = ¶m;
}
B* m_b;
};
A obj;
setup()
{
B b;
obj = A(b);
//after this function ends b is considered destroyed
}
loop()
{
//the following line accesses a member of the already destroyed object
print(obj.m_b->num);
}
Этот тестовый пример демонстрируетпо сути то же самое «использование после освобождения», что и в вашем коде (он, вероятно, не будет аварийно завершать работу, но он будет содержать то же неопределенное поведение).
На мой взгляд, PubSubClient
получение ссылки на клиента и сохранение указателя для последующего использования является плохой моделью.Нужно взять указатель на клиента, чтобы было более очевидно, что именно так и происходит.