在下面的代码中,我在执行mqtt.publish()时遇到崩溃,但只有当wificlient是局部变量时才会发生这种情况 - 如果wificlient是一个全局变量,问题就会消失。
我认为不需要了解底层库。
关于指针/垃圾收集必须有一个微妙的或不是什么导致这一点。我多年来一直在做C#,对C ++的经验要少得多。
#include <PubSubClient.h>
#include <WiFiClient.h>
void mqttSubs(char* topic, byte* payload, unsigned int length) {}
// if this line is moved inside setup() then the call to publish will crash
WiFiClient wifiClientGlobal;
PubSubClient mqttClient;
void setup() {
//WiFiClient wifiClientGlobal;
mqttClient = PubSubClient(mqttServer, mqttPort, mqttSubs, wifiClientGlobal);
mqttClient.connect("ESP8266Client", mqttUser, mqttPassword );
}
void loop() {
mqttClient.publish("repro/global", "sending message");
}
任何人都可以对此有所了解吗?
在PubSubClient上没有太多的过时,只是(imo)糟糕的文档和suboptiomal 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
引用客户端并存储指针供以后使用是一个糟糕的模式。它应该采用指向客户端的指针,以便更明显地发生这种情况。