本帖最后由 danielhuang 于 2019-3-25 21:09 编辑
http://www.openedv.com/forum.php?mod=viewthread&tid=289792&extra=
续上贴@freethink @wcyingdream
内存管理
经过两三天的观察,发现天气在两三个小时后就不再更新了,调用串口看接收天气信息正常,就是LCD不再更新信息。
初步估计是内存资源被耗尽所至。后面调用了内存使用率函数my_mem_perused()查看内存使用情况,便正实我了的想
法。LCD右边红 {MOD}的四位数字是内存使用率,精度是0.x%。天气程序是初始化后,每一分钟调用函数更新一次,结果内存
资源使用率就在被每次更新后上升0.5%。所以程序会在200分钟后申请不到内存而停止更新。我查看了程序,基本每个
mymalloc 都 myfree 了。现在请求大家帮助看看问题在哪里,谢谢。
//获取一次实时天气
//返回:0---获取成功,1---获取失败
u8 get_current_weather(void)
{
u8 *p;
u8 res;
// u8 ipbuf[16]; //IP缓存
p=mymalloc(SRAMIN,40); //申请40字节内存
sprintf((char*)p,"AT+CIPSTART="TCP","%s",%s",WEATHER_SERVERIP,WEATHER_PORTNUM); //配置目标TCP服务器
res = atk_8266_send_cmd(p,"OK",200);//连接到目标TCP服务器
if(res==1)
{
myfree(SRAMIN,p);
return 1;
}
delay_ms(300);
atk_8266_send_cmd("AT+CIPMODE=1","OK",100); //传输模式为:透传
// atk_8266_get_wanip(ipbuf);//获取WAN IP
USART3_RX_STA=0;
atk_8266_send_cmd("AT+CIPSEND","OK",100); //开始透传
printf("start trans...
");
u3_printf("GET
https://api.seniverse.com/v3/wea ... =zh-Hans&unit=c
");
delay_ms(20);//延时20ms返回的是指令发送成功的状态
// atk_8266_at_response(1);
USART3_RX_STA=0; //清零串口3数据
delay_ms(1000);
// atk_8266_at_response(0);
if(USART3_RX_STA&0X8000) //此时再次接到一次数据,为天气的数据
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//添加结束符
}
parse_now_weather();
atk_8266_quit_trans();//退出透传
atk_8266_send_cmd("AT+CIPCLOSE","OK",50); //关闭连接
myfree(SRAMIN,p);
return 0;
}
//解析当前天气
u8 parse_now_weather(void)
{
cJSON *root;
cJSON *pSub;
cJSON *arrayItem;
cJSON *pItem;
cJSON *pSubItem;
cJSON *pChildItem;
char *pr,*utf8str,*gbkstr;
// u8 size = 0;
int len;
u8 res;
u8 temperature;
root = mymalloc(SRAMIN,sizeof(cJSON));
pSub = mymalloc(SRAMIN,sizeof(cJSON));
pItem = mymalloc(SRAMIN,sizeof(cJSON));
pSubItem = mymalloc(SRAMIN,sizeof(cJSON));
pChildItem = mymalloc(SRAMIN,sizeof(cJSON));
arrayItem = mymalloc(SRAMIN,sizeof(cJSON));
pr = mymalloc(SRAMIN,1000);
utf8str = mymalloc(SRAMIN,50);
gbkstr = mymalloc(SRAMIN,50);
memset(pr,0,1000);
memset(gbkstr,0,50);
memset(utf8str,0,50);
file = mymalloc(SRAMIN,sizeof(FIL));
res=f_open(file,(const TCHAR*)APP_ASCII_5427,FA_READ);//打开文件
if(res==FR_OK)
{
asc2_5427 = mymalloc(SRAMIN,file->obj.objsize);
if(asc2_5427 != NULL)
{
res = f_read(file,asc2_5427,file->obj.objsize,&br);
}
f_close(file);
}
printf("jieshou->1dayjson = %s
",USART3_RX_BUF);
root = cJSON_Parse((const char*)USART3_RX_BUF);
if(root != NULL)
{
pSub = cJSON_GetObjectItem(root,"results");
if(pSub != NULL)
{
// size = cJSON_GetArraySize(pSub);
arrayItem = cJSON_GetArrayItem(pSub,0);
pr = cJSON_Print(arrayItem); //获取jsom数组
pItem = cJSON_Parse(pr); //对数组,进行升级。
if(pItem != NULL)
{
pSubItem = cJSON_GetObjectItem(pItem,"location");
if(pSubItem != NULL)
{
pChildItem = cJSON_GetObjectItem(pSubItem,"name");
if(pChildItem != NULL)
{
utf8str = pChildItem->valuestring;
SwitchToGbk((const u8*)utf8str,strlen(utf8str),(u8 *)gbkstr,&len); //获取城市名称转换为gbk文件
Show_Str(0,0,lcddev.width,lcddev.height,(u8 *)gbkstr,32,0); //显示城市名称。
printf("定位:%s
",(u8 *)gbkstr); //自己添加
}
}
// memset(utf8str,0,50);
memset(gbkstr,0,50);
pSubItem = cJSON_GetObjectItem(pItem,"now");
if(pSubItem != NULL)
{
pChildItem = cJSON_GetObjectItem(pSubItem,"text"); //获取天气信息。多云
if(pChildItem != NULL)
{
utf8str = pChildItem->valuestring;
SwitchToGbk((const u8*)utf8str,strlen(utf8str),(u8 *)gbkstr,&len);
POINT_COLOR = GBLUE;
Show_Str(410,40,lcddev.width,lcddev.height,(u8 *)gbkstr,32,0); //显示多云
LCD_ShowString(410,40,500,32,32,(u8*)gbkstr);
printf("天气:%s
",(u8 *)gbkstr); //自己添加
}
// memset(utf8str,0,50);
// memset(gbkstr,0,50);
pChildItem = cJSON_GetObjectItem(pSubItem,"code"); //获取气象代码
if(pChildItem != NULL)
{
gbkstr = pChildItem->valuestring;
show_weather_icon((u8 *)gbkstr,0); //根据气象代码,更新图片
}
// memset(gbkstr,0,50);
pChildItem = cJSON_GetObjectItem(pSubItem,"temperature"); //获取温度信息
if(pChildItem != NULL)
{
gbkstr = pChildItem->valuestring;
temperature = str2int((u8 *)gbkstr);
gui_show_num(280,90,2,RED,54,temperature,0x80);
gui_show_num(610,90,4,RED,54,my_mem_perused(SRAMIN),0x80);
printf("温度:%s
",(u8 *)gbkstr); //自己添加
}
}
pSubItem = cJSON_GetObjectItem(pItem,"last_update");
if(pSubItem != NULL)
{
gbkstr =pSubItem->valuestring;
POINT_COLOR = WHITE;
LCD_ShowString(0,188,300,12,12,(u8*)gbkstr);
printf("最后更新时间: %s
",(u8*)gbkstr);
//LCD_ShowString(60,110,200,16,16,"Font Update Success!");
}
}
cJSON_Delete(pItem);
myfree(SRAMIN,pItem);
}
}
cJSON_Delete(root);
myfree(SRAMIN,root);
myfree(SRAMIN,pSub);
myfree(SRAMIN,pItem);
myfree(SRAMIN,pSubItem);
myfree(SRAMIN,pChildItem);
myfree(SRAMIN,arrayItem);
myfree(SRAMIN,pr);
myfree(SRAMIN,utf8str);
myfree(SRAMIN,gbkstr);
myfree(SRAMIN,file);
myfree(SRAMIN,asc2_5427);
return 0;
}
只要你每次使用完,都释放了,就不会存在内存泄漏的
已查明,程序运行时申请的内存到调用结束前都有全部释放了。
但因为cjson解释里对一些mymalloc得来的指针值进行了修改或重新的赋值(cjson对象提取),而修改和重新赋值后的指针所指向的数据比原来的少,导致最后myfree时释放的内存变少了,间接导致 "内存泄漏" 。请问原子哥看懂我说的意思吗?请问有什么方法能解决?谢谢
例如:
char *pr;
pr = mymalloc(SRAMIN,1000);
pr = cJSON_Print(arrayItem); //获取json数组
pItem = cJSON_Parse(pr); //对普通json串处理成json对象
myfree(SRAMIN,pr);
pr申请时大小为1000字节,但后来由于指针给重新赋值,指向的数据大小已经不再时1000(比1000少,只有300),释放时只有300字节。
请问有什么方法可以处理这个问题??
一周热门 更多>