You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Paho MQTT C库v1.3.13异步模式时,消息到达回调函数被单次消息触发两次的原因咨询

Paho MQTT C库v1.3.13异步模式时,消息到达回调函数被单次消息触发两次的原因咨询

我仔细看了你的代码和问题描述,回调被触发两次的问题大概率和消息回调函数里没有正确释放库分配的资源有关,咱们一步步拆解:

核心原因:回调函数未正确释放MQTT消息资源

Paho MQTT C库的异步模式下,当消息到达触发messarri回调时,topicName和MQTTAsync_message都是由库在堆上分配的内存,你必须在回调函数结束前主动释放这些资源,不管消息是否有效。

看你的回调代码:

int messarri(void* context, char* topicName, int topicLen, MQTTAsync_message* message) {
    if(topicName!=NULL && (message->payload)!=NULL && message->payloadlen>0) {
        printf("\r\nmessage arrive\r\n");
        // ... 处理消息的逻辑
        message->payloadlen=0; // 你手动修改了payloadlen,但这无法替代资源释放
    } else {
        MQTTAsync_freeMessage(&message);
        MQTTAsync_free(topicName);
    }
    return 0;
}

你只在else分支释放了资源,但正常处理消息的if分支里完全没释放!库会认为你没有处理完这条消息,或者因为内存泄漏导致内部状态异常,进而再次触发回调来“提醒”你处理,这就是单次消息触发两次回调的直接原因。

其他可能的辅助因素

  • 持久会话设置:你把con_opts.cleansession=0(开启持久会话),如果客户端之前有未确认的离线消息,可能会出现重复推送,但结合你“单次发送触发两次”的描述,这个是次要因素,核心还是资源未释放的问题。
  • 库版本边缘问题:v1.3.13是相对老旧的版本,升级到最新的v1.3.15可能会修复一些小bug,但先解决资源释放的问题是关键。

修复后的回调函数示例

修改回调函数,确保不管消息是否有效,都在函数末尾主动释放库分配的资源:

int messarri(void* context, char* topicName, int topicLen, MQTTAsync_message* message) {
    if(topicName!=NULL && message->payload!=NULL && message->payloadlen>0) {
        printf("\r\nmessage arrive\r\n");
        printf("topic is : %s\r\n", topicName);
        printf("payload_len = %d\r\n", message->payloadlen);
        printf("receive message : %.*s\r\n", message->payloadlen, (char*)message->payload);
    }
    // 无论消息是否有效,都必须释放库分配的资源
    if(topicName != NULL) {
        MQTTAsync_free(topicName);
    }
    MQTTAsync_freeMessage(&message);
    return 0;
}

注意:不要手动修改message->payloadlen,这完全没必要,库只关心你是否调用了标准的释放函数来回收资源。

额外提醒

你现在通过message->payloadlen=0“规避”了段错误,但这是治标不治本的。正确释放资源后,不仅不会再出现回调触发两次的问题,还能从根源上避免内存泄漏和潜在的程序崩溃风险。


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 13:24:50