在使用STM32调试一个模块的时候,我在初始化完成之后,发现程序一直停留在某一个地方,无法进入while主循环中,每一次运行这一个函数,都会出现这种问题。这个函数核心部分是这样的
void atk_8266_apsta_test_get(u8* host,u8* url1)
{
u8 timex=0;
u8 p[30];
u16 t=999;
u16 rlen=0;
u8 constate=0; //Á¬½Ó״̬
atk_8266_send_cmd("AT+CWMODE=3","OK",50);
atk_8266_send_cmd(p,"OK",1000);
sprintf((char*)p,"AT+CIPSEND=0,%d",strlen(url1));
atk_8266_send_cmd(p,"OK",200);
sprintf((char*)p,url1);
atk_8266_send_cmd(p,"OK",200); //
sprintf((char*)p,"AT+CIPSEND=0,%d",strlen(url1));
atk_8266_send_cmd(p,"OK",200);
delay_ms(200);
}
调用的程序如下所示。
u8 host_url1[20]="gxyusan.zztv021.com";
u8 url1[120]="GET /api/HomePage/Getumbrellastatus?umbrella_house_id=2&sign=3 HTTP/1.1\r\nHost:gxyusan.zztv021.com\r\n\r\n";
atk_8266_apsta_test_get(host_url1,url1);
打开Debug设置断点调试之后,发现程序运行到这个函数结尾的时候,一直会出现Cannot access Memory。根据提示应该是找不到while主循环对应的入口地址了。那么合理推测应该是这个程序中的变量影响了之后的主函数的地址,或者说这个函数内部的指针溢出了.
经过一番排查,发现问题就出在指针p上,定义的时候定义为unsigned char p[30];说明这个常指针p指向的字符串的长度为30,但是在程序中出现了
sprintf((char*)p,url1);
这一句将整个url赋值给了p那么p目前装的字符串长度和url一样,有101个,此时已经超出了30的范围,导致原先存放while主循环的地址的那部分内存的内容被修改,可能被修改为一个已经超出单片机内存范围的地址。因此出现了Cannot access Memory。
无法根据指针内容找到程序入口的错误。
解决的方法就是将p指针的空间变大,足够放下url即可。比如,unsigned char p[200].那么程序就可以正常运行。
这里记录一下
c语言中char* p = "Hello";和char p[] = "Hello";的p有什么区别。
这两个表达式的p都是存储字符H的地址的指针。它们的区别是:*p中的p是普通指针,可以进行++、--操作,但它指向的Hello是常字符串,不能修改(就是不能写操作),所以像*(p+1)='x';这样的语句是非法的;但这个p可以指向别处,如有char *s="123";,则p=s;合法。而p[]中的p是常指针,不能++、--操作,也不能指向别处,但它指向的字符串Hello不是常字符串,可以修改,如*(p+1)='x';则是合法的,执行后原字符串就成了Hxllo了