打印
[PIC®/AVR®/dsPIC®产品]

函数内部局部变量计算有错误?

[复制链接]
5628|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wooda|  楼主 | 2021-8-22 18:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 wooda 于 2021-8-22 18:31 编辑

各位好
有个问题困惑我一段时间了:
就是函数内部局部变量,有的时候计算会有问题:
具体见图:
这里几个变量都是函数内部局部变量工程比较大,也不是每个函数里面局部变量都会这样,像这里下一行widthy的计算就是正确的。
编译环境是MPLABX 4.20,XC8,1.45,pickit4直接硬件仿真执行。

不知道各位有没有碰到类似的问题?
或者这个问题可能是什么地方的原因?可以怎样排查?

先谢谢了~


使用特权

评论回复
沙发
纪国圣| | 2021-8-22 21:15 | 只看该作者
遇到过类似的问题,不过不是这个型号的单片机。当时遇到这个问题的原因推测是有可能栈太小,数据被覆盖。后来改为全局变量就没问题了。

使用特权

评论回复
板凳
wooda|  楼主 | 2021-8-22 23:41 | 只看该作者
本帖最后由 wooda 于 2021-8-22 23:43 编辑
纪国圣 发表于 2021-8-22 21:15
遇到过类似的问题,不过不是这个型号的单片机。当时遇到这个问题的原因推测是有可能栈太小,数据被覆盖。后 ...
我也怀疑过堆栈溢出,不过这里没有函数调用,就是简单的加减法,应该不会调用库里运算子函数,直接是当前位置执行汇编指令运算的。
看着几个变量的地址,中间这个变成错误值,0x12A和0x153地址的值都对,0x152地址就不对了?
而且看过编译输出警告信息,也没有报堆栈溢出警告。。。

使用特权

评论回复
地板
waaini| | 2021-8-23 11:18 | 只看该作者
这只能看看汇编指令的具体过程了呀

使用特权

评论回复
5
lcczg| | 2021-8-23 14:25 | 只看该作者
升级到最新的软件再编译调试看看。

使用特权

评论回复
6
zlf1208| | 2021-8-23 15:04 | 只看该作者
本帖最后由 zlf1208 于 2021-8-23 15:14 编辑

局部变量用后即弃,在第二次调用这个函数时该变量并非是上一次退出时候的值,如果需要使用上次调用时的结果,就不能采用局部变量。概念一定要清楚,什么是局部变量,什么是全局变量,什么是函数的形参和实参,每种变量在使用时有什么要求,全局变量又会有什么付作用,只有深刻理解基本定义,所写的程序才不会有Bug,要知道调试的结果正确并非说明程序就是正确的,没有Bug的,结果正确不代表过程正确。

任何变量一定要先定义,然后赋初值再使用,定义的时候给初值和程序中给初值二者有什么差异?这些都是细节,但是都必须十分清楚自己在做什么,为什么要这样做。


请牢记:程序的正确性是设计出来的,不是调试出来的,虽然调试是程序设计的必要环节!

使用特权

评论回复
7
wooda|  楼主 | 2021-8-23 15:47 | 只看该作者
zlf1208 发表于 2021-8-23 15:04
局部变量用后即弃,在第二次调用这个函数时该变量并非是上一次退出时候的值,如果需要使用上次调用时的结果 ...

说的很正确,没错,变量生存期大家也很清楚,使用前要赋值,如果这个概念没有,那么将面对无数的bug。编译时候也会针对使用未赋值变量进行warning的。
在这里的问题里面,我自然是单步执行发现问题了才提出来,这里抓变量值也是实时抓,只不过截图时候跳到后面一点了。
同一个程序段内,局部变量互相之间是不会重复的,因为都有生存期。当然,代码最终优化的时候会合并也是有可能的。这里我代码优化没有开。代码优化开了之后的单步,和没开时候的单步,执行的step是完全不一样的。

使用特权

评论回复
评论
zlf1208 2021-8-23 16:23 回复TA
另外,如果有中断也可能会导致问题的 
8
wooda|  楼主 | 2021-8-23 16:02 | 只看该作者
waaini 发表于 2021-8-23 11:18
这只能看看汇编指令的具体过程了呀

我和你的想法一致,所以第一时间是冲到汇编里面去看。
这个加法很简单,大概7,8行指令就完成了。看了没发现什么问题。
最后我建了个全局数组
将endx,startx,widthx依次赋值进入数组1,2,3,然后加法之后再赋值进入4,5,6
发现结果并没有问题。
所以问题大约指向了调试器对变量表的变量地址翻译过程以及根据地址取值的过程中,应该是有错误,这个错误不是每次都会发生,有一定概率会取错值。我思考了一下,可能和对齐有关。
算了,不依赖调试器的值显示,用个数组+count依次循环取值就完事了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

45

主题

465

帖子

1

粉丝