在下面的代码中,我在执行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");
}
任何人都可以阐明吗?
没有太多的升华,只是(imo)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
参考客户端并存储指针以供以后使用是不良模式。应该向客户指针,以使这是发生的事情。