你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

sprintf使用的奇怪现象,怀疑for循环控制变量有BUG

[复制链接]
kylongmu 提问时间:2017-7-26 22:44 /
本帖最后由 kylongmu 于 2017-7-28 12:56 编辑

使用平台NUCLEO 767ZI以下代码
printf.jpg
现象描述,当调用100次以后,第二个printf会被执行到。把字符数组大小改为200后,调用200次后,第二个printf有打印输出。测试几组数组大小,均出现严格的错误现象。
目前怀疑sprintf函数影响,或者是for循环体导致循环变量i在离开for结构后被不正确的置零了。
------------------------------------------------
工程生成:
CUBEMX 4.22
------------------------------------------------问题已解决:FreeRTOS默认线程里的Stack size是128字节,我的程序是放到线程里的,估计是变量申请越界了,调整此处Stack size 到256字节问题解决。
前面一个CDC主机找不到设备的问题,感谢act8238建议加大Heap size解决。
也感谢moyanming2013对我程序中问题的挑剔,toofree的热心帮忙。
总结一下:CubeMX以及FreeRTOS为了突出性能,空间占用小,默认设置的Heap与Stack尺寸很小,必须小心,尤其是当使用USB,sprintf这类会动态申请空间的库时。而出错的现象却很难定位。





<
收藏 1 评论38 发布时间:2017-7-26 22:44

举报

38个回答
toofree 回答时间:2017-7-28 02:43:25
提一点意见。

楼主,老改主楼帖子,这样不好。
帖子错了,可以往上加,备注一下什么时间修改过什么东西。
你这样老改,让其它人看到回复的楼层,不知道怎么回事。换种说法,你这样是对回复你帖子和看你帖子人的不尊重。
anobodykey 回答时间:2017-7-27 09:32:44
楼上正解,你的char * Dbg_QMsg[100]是指针数组,即有100个数组,每个里面都是一个指针,你100的时候Qmsg就已经溢出了
Dandjinh 回答时间:2017-7-27 09:16:30
试一下把 char * Dbg_QMsg[100]; 改为 char Dbg_QMsg[100]; 看看
kylongmu 回答时间:2017-7-26 22:56:04
本帖最后由 kylongmu 于 2017-7-27 17:21 编辑

kylongmu 回答时间:2017-7-26 23:15:18
检查发现,当循环到缓冲区大小时,字符串的第一个字符会被sprintf打印为'\0',而puts是以'\0'为输出结束的,为啥会这样呢?
kylongmu 回答时间:2017-7-27 00:43:48
本帖最后由 kylongmu 于 2017-7-27 17:22 编辑

改正语法错误,现象依旧,换代码测试定位问题,
目前测试sprintf的内容没有问题,看来是for循环里的变量i有问题,另外一组代码来做测试:
char Dbg_QMsg[100];
uint8_t P_msg1[]="Err\n\r";
        sprintf(Dbg_QMsg,"Hello %d\n\r\0",i);
        for(i=0;i<100;i++)
        {
                if(Dbg_QMsg【i】=='\0')//不用中文括号,这里无法显示
                {
                        if(i==0)
                                HAL_UART_Transmit(&huart3, P_msg1,sizeof(P_msg1), 0xFFFF);//不会执行
                        break;
                }
        }
        if(i==0)
                HAL_UART_Transmit(&huart3, P_msg1,sizeof(P_msg1), 0xFFFF);//会执行到
在for循环体内i不会等于0,但是循环体外在循环字符分配大小次数后,i就会变为0,而且是在循环数大于等于字符数组分配空间的情况下才会出现。
wuqt 回答时间:2017-7-27 08:54:44
改一下类似iar里的library options的优化参数试试,标准库一般不会有问题的。
MrJiu 回答时间:2017-7-27 09:11:51
百度一下sprintf,有惊喜哦!!!
kylongmu 回答时间:2017-7-27 09:38:55
本帖最后由 kylongmu 于 2017-7-27 17:20 编辑

多谢各位大神的意见。
我用的是CubeMX生成的keil工程,目前可以确认的是编译优化等级从o1到o3,都出现相同的状况,就是for循环体外变量被置零,而且是根据设置的缓冲区大小决定循环次数。
keil里面用的是5.06版本的编译器,还有个6.4编译器,可是一换6.4就一堆错误出来,无法编译,看来目前的CubeMX还没有更新支持keil的新编译器,关于这点各位有什么建议。
char Dbg_QMsg[100];
uint8_t P_msg1[]="Err\n\r";
        sprintf(Dbg_QMsg,"Hello %d\n\r\0",i);
        for(i=0;i<100;i++)
        {
                if(Dbg_QMsg【i】=='\0')//不用中文括号,这里无法显示
                {
                        if(i==0)
                                HAL_UART_Transmit(&huart3, P_msg1,sizeof(P_msg1), 0xFFFF);//不会执行此处
                        break;
                }
        }
        if(i==0)
                HAL_UART_Transmit(&huart3, P_msg1,sizeof(P_msg1), 0xFFFF);//会执行此处
也就是说变量i一旦出了for循环体就被置零了,而且这种现象是循环次数达到Dbg_QMsg[100]分配的大小数来决定的,如果循环99次以内,出了for,i并不会变0;一旦大于等于100,出了for后i就会被置零;奇怪的是把空间分配为200的数组,那么问题点就变成199了。
另外char Dbg_QMsg[100]不论是申明为全局,还是局部变量,还是static,还是volatile,结果都一样。
wuqt 回答时间:2017-7-27 10:29:09
kylongmu 发表于 2017-7-27 09:38
多谢各位大神的意见。
我用的是CubeMX生成的keil工程,目前可以确认的是编译优化等级从o1到o3,都出现相同 ...

不是那个编译优化,是iar 里 project-options-general options - library options,针对 printf scanf 库的优化!
如果仍不行可以在win32里编译运行测试下,找找问题!
1234下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版