兄弟,我现在有一个项目使用了WIFI+MQTT+cJSON这三种东西,并且也遇到了这个问题。
出现的问题是:板子上电后连接AP,每隔1s,将传感器采集的数据打包为json格式,并且用cJSON_print函数将数据转换为字符串,然后通过MQTT发送到服务器上。服务器能连续接收接近9min的数据,之后就报你描述的那种错误。
后来翻遍各种论坛,发现大家都说是内存泄漏导致的问题,于是我就在发送传感器数据完成后打印堆内存的大小,一看问题就出现了。每发送一次传感器数据到MQTT服务器上,堆内存就减少250左右,如下图所示:
I (2906) MQTT_CLIENT: MQTT_EVENT_CONNECTED
I (3259) MAIN: free Heap:130036
I (4272) MAIN: free Heap:129756
I (5273) MAIN: free Heap:129540
I (6265) MAIN: free Heap:129308
I (7268) MAIN: free Heap:129028
I (8271) MAIN: free Heap:128768
I (9262) MAIN: free Heap:127412
最终堆内存降到3000左右报错,从左边的时间可以看到大概持续了8分钟:
I (518265) MAIN: free Heap:3516
I (519213) wifi:bcn_timeout,ap_probe_send_start
I (519264) MAIN: free Heap:3392
I (520266) MAIN: free Heap:3516
I (521265) MAIN: free Heap:3516
I (521717) wifi:ap_probe_send over, resett wifi status to disassoc
I (521718) wifi:state: run -> init (c800)
I (521719) wifi:pm stop, total sleep time: 315778659 us / 520005068 us
I (521723) wifi:<ba-del>idx:0, tid:0
I (521726) wifi
<11,0>, old:<11,2>, ap:<255,255>, sta:<11,2>, prof:1
由于我之前测量过发送的传感器数据占用的字节数大小也为250左右,所以怀疑是使用cJSON_print函数后没有free掉堆内存。
后来在发送完数据后free掉内存,代码如下:
Code: Select all
json_string=cJSON_Print(root);
esp_mqtt_client_publish(mqtt_client, MQTT_TOPIC, json_string, 0, 0, 0);
free(json_string);
然后再打印堆内存的大小:
Code: Select all
ESP_LOGI(MAIN_TAG, "free Heap:%d", (int)esp_get_free_heap_size());
可以看到运行了16分钟堆内存基本不变
I (82202) MAIN: free Heap:130040
I (83198) MAIN: free Heap:130040
I (84198) MAIN: free Heap:130044
I (85198) MAIN: free Heap:130044
I (86190) MAIN: free Heap:130040
I (87199) MAIN: free Heap:130040
I (88195) MAIN: free Heap:129916
I (89197) MAIN: free Heap:130040
I (90198) MAIN: free Heap:130040
I (1006197) MAIN: free Heap:129992
I (1007200) MAIN: free Heap:129992
I (1008199) MAIN: free Heap:129992
I (1009202) MAIN: free Heap:129984
I (1010197) MAIN: free Heap:129992
我在文心一言上问了cjson_print的一些问题,好像它也可以使用栈内存,这样就不需要在每次发送完数据后释放内存了。但还没实践过,大家可以试一试,文心一言的代码如下:
Code: Select all
char buffer[1024];
cJSON *root = cJSON_CreateObject();
// ... 填充 cJSON 对象 ...
int len = cJSON_PrintPreallocated(root, buffer, sizeof(buffer), 0);
if (len < 0) {
// 处理错误
}
// 使用 buffer 中的字符串
// ...
// 不需要释放 buffer 的内存,因为它是栈上分配的