makesoft 发表于 2019-12-1 20:26:23

两天时间解决了一个BUG,函数再入引起,不要忽视警告信息

本帖最后由 makesoft 于 2019-12-1 20:58 编辑

没想到51的小程序调试起来这么麻烦,花了整整两天时间,让俺这老江湖汗颜。

其实就是偷懒造成的,一个函数在程序初始化时使用,这个时候系统任何中断并没有打开,另外这个函数在定时中断中也有使用,天真的认为不存在同时调用的可能,所以不可能存在再入的问题,就是没理会重复调用的告警信息。

后来程序不定时的出现问题,因为开始已经有了不可能同时调用再入这个函数的场合,所以就没有检查这个问题。

实在没有办法,刚才检查MAP信息,TNND才发现,其实不仅仅有再入的问题,这个函数使用的局域变量占用的地址,有一个是和其他函数是重复覆盖使用的,真相大白了,两天时间就是不想写一个reentrant,因为会增加一点点代码。{:sweat:}

rube 发表于 2019-12-1 20:52:14

函数同时被调用了?局部变量被赋值,不是期望的值

wye11083 发表于 2019-12-1 22:02:58

lz,c代码函数里面的变量都在栈里面,不可能出现地址重复的

了无 发表于 2019-12-1 22:52:00

函数局部变量是定义在栈里面的,肯定会和其他函数的局部变量重合。我说的没错吧?

makesoft 发表于 2019-12-1 22:59:10

wye11083 发表于 2019-12-1 22:02
lz,c代码函数里面的变量都在栈里面,不可能出现地址重复的

keil c51优化的时候会判断函数会不会嵌套调用,不存在这种关系的话存在局域变量复用的问题。
并不是所有编译器局域变量都是栈操作的。

johnlj 发表于 2019-12-1 23:40:38

一个函数在程序初始化时使用,这个时候系统任何中断并没有打开

初始化后,函数已经执行完退出,不会影响第一次中断调用的

倒是怀疑定时中断时间间隔过小,造成前次中断未返回,后次中断又来了,没做再入函数设置,当然会出问题

makesoft 发表于 2019-12-1 23:47:25

johnlj 发表于 2019-12-1 23:40
一个函数在程序初始化时使用,这个时候系统任何中断并没有打开

初始化后,函数已经执行完退出,不会影响第 ...

哈哈,就是一样的思维才导致查了两天才解决问题。
当中断和主程序共同可以调用一个函数的时候,这个函数不是再入属性,编译器优化这个函数局域变量占用内存的时候,可能和主程序其他函数做覆盖优化,这个时候问题就发生了,哪怕仅仅覆盖一个字节。
当局域变量不是静态分配而是堆栈的话,就没有这个问题发生了。

wye11083 发表于 2019-12-1 23:55:31

makesoft 发表于 2019-12-1 23:47
哈哈,就是一样的思维才导致查了两天才解决问题。
当中断和主程序共同可以调用一个函数的时候,这个函数 ...

我ca,我想到之前用avr8时,gcc编译的代码在超过8kb之后会产生各种莫名其妙的问题,死机,执行异常,中断异常,等等。。。貌似是同一类问题。汇编都查了,始终无解,最后放弃avr了

johnlj 发表于 2019-12-1 23:59:48

makesoft 发表于 2019-12-1 23:47
哈哈,就是一样的思维才导致查了两天才解决问题。
当中断和主程序共同可以调用一个函数的时候,这个函数 ...

看明白是,是初始化调用该函数后,其占用的临时变量空间的某个字节被其它函数使用,然后中断中该函数继续使用原来的临时变量空间,就出现了bug

那么减低编译优化级别,会不会避开这个问题?

makesoft 发表于 2019-12-2 06:26:07

默认优化8级,并且64K程序空间现在只剩余几百字节,不然也不吝啬使用reentrant啊

takashiki 发表于 2019-12-2 06:56:28

makesoft 发表于 2019-12-2 06:26
默认优化8级,并且64K程序空间现在只剩余几百字节,不然也不吝啬使用reentrant啊 ...

搞成11级优化,全局寄存器着色,您试下,估计能剩余2kB代码空间出来

stm32f103f4 发表于 2019-12-2 07:27:49

不知道不开优化会是什么情况

McuPlayer 发表于 2019-12-2 08:06:03

这个只能养成习惯
中断中尽量避免调用子函数,实在需要,就写成专门给这个中断用的,不同的中断之间也是要这样隔离
复杂的主逻辑,全部放在主程序里,调用复杂层次的子函数结构

lb0857 发表于 2019-12-2 08:11:47

中断中尽量避免调用子函数,实在需要,就写成专门给这个中断用的,不同的中断之间也是要这样隔离    最实用 接地气的建议{:handshake:}

823032003 发表于 2019-12-2 08:13:23

楼主,请问当函数内部局域变量不是静态分配而是堆栈的话,就没有这个问题吗?

myxiaonia 发表于 2019-12-2 08:13:34

我之前也犯过和你一样的错误,搞两天没搞明白,后来还是求助后发现的问题。

和你一样,同一个函数中断和应用程序都有调用,我是中断指定了寄存器组,而调用函数却没指定,然后keil没有任何报警,就这么被坑了两天

myxiaonia 发表于 2019-12-2 08:14:18

823032003 发表于 2019-12-2 08:13
楼主,请问当函数内部局域变量不是静态分配而是堆栈的话,就没有这个问题吗? ...

是的加重入后会使用栈

saccapanna 发表于 2019-12-2 08:56:09

上次在一个帖子里提到函数可重入性的问题,被人嗤之以鼻,觉得自己没有这些概念,同样写了好多程序。最怕根本没有这个概念的人,还觉得自己写的程序很“完美”。

saccapanna 发表于 2019-12-2 08:57:24

本帖最后由 saccapanna 于 2019-12-2 09:02 编辑

wye11083 发表于 2019-12-1 22:02
lz,c代码函数里面的变量都在栈里面,不可能出现地址重复的

你说的这种函数,叫做纯函数,纯函数都是可以重入的。但是使用了全局变量等的函数(内部变量使用 static 修饰也是一样的),就不可重入了,或者要做保护。

at90s 发表于 2019-12-2 09:02:55

只有51才会有这个问题,keil c在连接时才分配局部变量的内存,它会分析函数调用关系来确定每个函数里各个局部变量的地址,这都是51硬件维护的栈空间只有256字节缘故。其他处理器一般都会吧局部变量在栈里面分配。

wuha 发表于 2019-12-2 09:17:12

keil c51默认的8级优化,我在读写矩阵键盘时,总是固定的一个按键没反应,其他按键都没问题;换成按键程序一模一样,主程序不太一样的另一个板子上,还是按键有问题,但是换了个按键固定没反应。后来这两套程序都把优化等级改成0,就没有这个问题了,到现在都不知道啥原因。

newselect 发表于 2019-12-2 09:19:48

中断里不放函数就好啦, 要放就用全局变量或静态变量

luobote55 发表于 2019-12-2 09:23:19

0 warning, 0 error.

security 发表于 2019-12-2 09:27:54

takashiki 发表于 2019-12-2 06:56
搞成11级优化,全局寄存器着色,您试下,估计能剩余2kB代码空间出来

请教一下,11 级优化,我怎么看到只有 9 级呢,在哪里设置?

laujc 发表于 2019-12-2 09:57:19

你这个还好解决,上次用renesas的EEPROM Flash库,直接覆盖变量值,那找起来才痛苦。。。
因为那个库是不开源的,后来还是根据网上的提示,猜出是这个问题,重新定义了dr文件才搞定。

armstrong 发表于 2019-12-2 10:01:35

wye11083 发表于 2019-12-1 22:02
lz,c代码函数里面的变量都在栈里面,不可能出现地址重复的

你错了,pic的c编译器你去试试。
而且,51的c编译器也有这种模式

armstrong 发表于 2019-12-2 10:05:22

本帖最后由 armstrong 于 2019-12-2 10:08 编辑

我用过pic,51的c编译器,这两个编译器都有一种没有栈的编译模式,函数的局部变量其实都是全局变量复用。
特别是pic8,根本没有别的选择!51还有得选,pic8在硬件上就没有栈。
所以用了arm之后,再也不想用pic和51了,这些芯片是半残废。
就是最简陋的cortex-m0,也是完整的c语言支持,完整的32为平面寻址。

security 发表于 2019-12-2 10:13:20

armstrong 发表于 2019-12-2 10:05
我用过pic,51的c编译器,这两个编译器都有一种没有栈的编译模式,函数的局部变量其实都是全局变量复用。
...

我也不想用的,可是谁叫它便宜{:mad:} 。

winterw 发表于 2019-12-2 10:21:47

多谢分享,标记一下

1a2b3c 发表于 2019-12-2 10:22:42

看到后一震,难道之前的串口也有这样的问题?初始化后没有到主循环之前调用了一下打印,然后开启定时器,后面定时器中会打印,当然编译也是同样的警告,莫非这样也存在隐患?想想害怕,不过从实际情况来看,这么多年了也没有哪里有问题,估计和优化有关吧?不优化应该可能没问题

takashiki 发表于 2019-12-2 10:30:31

security 发表于 2019-12-2 09:27
请教一下,11 级优化,我怎么看到只有 9 级呢,在哪里设置?

首先要在Device选项卡中设置使用LX51代替BL51,此时C51选项卡才会出现优化等级10和11,并且尽量使用AJMP/ACALL而不是LJMP/LCALL。

此时多出两个优化等级,而且尽可能少用LJMP/LCALL的选项由灰色变为可用。

security 发表于 2019-12-2 10:53:41

takashiki 发表于 2019-12-2 10:30
首先要在Device选项卡中设置使用LX51代替BL51,此时C51选项卡才会出现优化等级10和11,并且尽量使用AJMP/ ...

可以了,多谢赐教。
弄到 11 级,果然省了 1.8 K 的空间,不敢相信,就是不知道程序还能不能正常跑。

makesoft 发表于 2019-12-2 10:56:30

saccapanna 发表于 2019-12-2 08:56
上次在一个帖子里提到函数可重入性的问题,被人嗤之以鼻,觉得自己没有这些概念,同样写了好多程序。最怕根 ...

正常的,很多人估计最大代码长度也就是几K,大程序和小程序策略是不同的,这些东西不会注重的。

hell-prototypes 发表于 2019-12-16 14:34:07

涨知识了

zxq6 发表于 2019-12-16 14:50:55

printf是不是可重入的呢?我到处都在用printf,看各位的描述,担心ing

xiaoxiaobaiyu52 发表于 2019-12-16 22:06:18

zxq6 发表于 2019-12-16 14:50
printf是不是可重入的呢?我到处都在用printf,看各位的描述,担心ing

我上网查了,是不可重入的,涉及IO的都是

funnynypd 发表于 2019-12-17 04:32:57

>gcc编译的代码在超过8kb之后会产生各种莫名其妙的问题,死机,执行异常,中断异常,等等。。。貌似是同一类问题。汇编都查了,始终无解,最后放弃avr了
What is the size of the AVR (<=8K Bytes)?

嘀嘀 发表于 2019-12-17 23:22:39

刚参加工作那会,遇到过函数重入问题
还好当时老大经验丰富,很快指出问题所在了,感谢曾经的老大

kevinchen026 发表于 2019-12-18 00:48:10

还是技术贴看着有意思_

leicai05 发表于 2019-12-18 09:01:35

记得开始写程序的时候,写中断都是非常小心的,函数是一定不会在中断产生的,代码的长度都严格控制,能在主循环中写的一定不放入中断中。

慢慢的,现在也开始偷懒了,中断中也不时出现函数了,看来是警觉性落后了呀!!

makesoft 发表于 2019-12-18 09:08:04

leicai05 发表于 2019-12-18 09:01
记得开始写程序的时候,写中断都是非常小心的,函数是一定不会在中断产生的,代码的长度都严格控制,能在主 ...

其实我从来都不同意函数不放中断的这种说法,整个CPU运行时间计算好了,各种中断优先级事先规划好了,中断里的函数运行时间是可预测的,这样的程序是没有任何问题的。

天天说中断里面不放函数的,我搞不清楚程序代码量有多少,1000行还是10000行还是十万行?这几种情况当然做法也是完全异同的,大程序有大程序的构架,小程序有小程序的做法,不能一概而论。

leicai05 发表于 2019-12-18 09:27:44

makesoft 发表于 2019-12-18 09:08
其实我从来都不同意函数不放中断的这种说法,整个CPU运行时间计算好了,各种中断优先级事先规划好了,中 ...

哎,不知道你有没有体会过,小众行业,项目驱动的研发,老板和客户的需求总是随心所欲,有时候更是变态的;

“这个项目就是要快,慢了就黄了,你不知道竞争有多么激烈,要快,马上要发货......
这个中断处理信号10us后要跟随xx信号动作, 持续时间需要多100us。如果xx信号检测到了动作,又要xxxx.........”

无数个这样的需求,能有具体的要求还是不错的,就怕那种,老板和客户都只是要这个结果,具体怎么实现也不清楚,对于某些指标就是要反应快,
不得不在中断中完成。而且还可能跟持续时间扯上关系,还有就是好几个中断信号,相互交叉。发货就是要快!!!!

这种情况下,写出来捉急的代码可能性是很高的!!
老板的逻辑是,先拿出货物出去交给客户再说,就算以后有bug,生意至少还由得做;拿不出东西,生意就黄了。

makesoft 发表于 2019-12-18 09:34:05

leicai05 发表于 2019-12-18 09:27
哎,不知道你有没有体会过,小众行业,项目驱动的研发,老板和客户的需求总是随心所欲,有时候更是变态的 ...

确实是这样,相互理解吧,其实大家都有大家的苦衷。

我也讨厌程序修修改改,大修下来几次自己都不认识这程序是自己写的了{:lol:}

xintao 发表于 2019-12-18 16:45:01

不放过任何一条警告的默默飘过。
页: [1]
查看完整版本: 两天时间解决了一个BUG,函数再入引起,不要忽视警告信息