(求助)续[[STM32F7通过ESP8266获得网络时间和天气]]内存管理问题

2019-07-20 02:55发布

本帖最后由 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;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
12条回答
正点原子
1楼-- · 2019-07-20 05:32
 精彩回答 2  元偷偷看……
正点原子
2楼-- · 2019-07-20 10:40
八成是你申请了,没释放。检查办法,可以在每个函数的入口打印内存使用率,出口打印内存使用率,看下变化,就知道在哪个函数有问题了
danielhuang
3楼-- · 2019-07-20 11:16
 精彩回答 2  元偷偷看……
正点原子
4楼-- · 2019-07-20 14:34
danielhuang 发表于 2019-3-26 07:59
谢谢,原子哥的建议,我试试。目前是这样例如未调用之前使用率是3.5%,调用时是10.5%,调用完后是4.0% 这 ...

只要你每次使用完,都释放了,就不会存在内存泄漏的
danielhuang
5楼-- · 2019-07-20 19:57
本帖最后由 danielhuang 于 2019-3-27 15:02 编辑
正点原子 发表于 2019-3-27 02:20
只要你每次使用完,都释放了,就不会存在内存泄漏的

已查明,程序运行时申请的内存到调用结束前都有全部释放了。
但因为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字节。

请问有什么方法可以处理这个问题??


正点原子
6楼-- · 2019-07-20 22:18
 精彩回答 2  元偷偷看……

一周热门 更多>