WifiClient问题 - 必须是关于本地变量和全局变量的基本C / C ++问题

问题描述 投票:-1回答:1

在下面的代码中,我在执行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");
}

任何人都可以对此有所了解吗?

c++ arduino global-variables mqtt
1个回答
1
投票

在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 = &param;
    }
    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引用客户端并存储指针供以后使用是一个糟糕的模式。它应该采用指向客户端的指针,以便更明显地发生这种情况。

© www.soinside.com 2019 - 2024. All rights reserved.