本人小白一枚
最近在捣鼓ESP8266的NONOS_SDK开发,本来已经写好了一个工程测试基本功能也没什么问题了,但是发现了一个很严重的问题,就是每次一跑上40来分钟的时候,就会宕机重启,自动重启,真是奇了个怪了,本来这也没啥,但出于对稳定性的追求还是决定把这bug给补上。
一、问题复现
首先还是要确定,是不是就是同一个问题导致的宕机。每次都要等上40分钟还是挺痛苦的。
基本上能确定每次都是这里导致的宕机
二、找对应代码错误点
最奇怪的就是,网上的fatal exception基本上都会有像这样子的
Fatal exception 29(StoreProhibitedCause):
epc1=0x4000df64, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000
然而我的却没有……这bug不按常理出牌啊
顺便说一下通常的情况,像上述的fatal exception 我们是可以找到错误地址的,方法如下:
在 (*.S) 文件中找出对应的地址,添加打印以便定位问题。
Fatal exception 29(StoreProhibitedCause):
epc1=0x4000df64, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000
比如使用的是 user1.bin,那么就在 user1.S 中找到0x4000df64 地址,并查明对应的函数。
如果使用的是 flash.bin + irom0text.bin,可以在 eagle.S 中查找出错的地址。
虽然我们也未必能看得懂汇编,但是我们可以在附近找一找有没有类似函数名的标签从而定位代码的位置。
比方说
这个我们就能猜到可能是uart0_rx_intrx_handler的代码出了问题。
言归正传,现在这条寻常的思路断了,我们就只能不断通过输出信息来调试了,通过多次重现问题,发现每次在创建TCP连接时宕机的。
这就奇怪了,因为这代码我是抄的啊!2333333于是只能仔细读读这段代码了,反复读反复测,然后终于发现
/*
* 函数名: iot_station_init
* 描述: 以ESP8266为客户端,建立tcp连接
* 输入: remote_ip:服务器IP
* local_ip:本地IP
* remote_port:服务器端口
* 返回: true:成功
* 调用: 无
*/
bool ICACHE_FLASH_ATTR iot_station_init(struct ip_addr *remote_ip ,struct ip_addr *local_ip ,int remote_port )
{
#ifdef DEBUG
os_printf("\r\ncall iot_station_init\n");
#endif
os_printf("\r\n3");
user_tcp_conn.type = ESPCONN_TCP;
user_tcp_conn.state = ESPCONN_NONE;
user_tcp_conn.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
//
os_printf("\r\nuser_tcp_conn.proto.tcp: %X", user_tcp_conn.proto.tcp);
os_memcpy(user_tcp_conn.proto.tcp->local_ip ,local_ip,4);
os_memcpy(user_tcp_conn.proto.tcp->remote_ip ,remote_ip,4);
user_tcp_conn.proto.tcp->local_port = espconn_port();
user_tcp_conn.proto.tcp->remote_port = remote_port;
os_printf("\r\n4");
espconn_regist_connectcb(&user_tcp_conn ,user_tcp_connect_cb);
espconn_regist_reconcb(&user_tcp_conn ,user_tcp_recon_cb);
#ifdef DEBUG
os_printf("\nespconn_connect");
#endif
espconn_connect(&user_tcp_conn);
//os_free(user_tcp_conn.proto.tcp);
//os_printf("\r\nfree: %X", user_tcp_conn.proto.tcp);
os_printf("\r\n5");
return true;
}
这里每次都在申请堆空间,存储tcp设置项user_tcp_conn.proto.tcp,然而却重来没有释放。