请教函数重入问题之defualtC库和micorLIB库相关区别和联系!

2019-12-20 21:45发布

实验环境:
Keil MDK 5.23 + stm32f103vct6 + 未开启优化。

实验缘由:
实验中需要用到一个数据,该数据参与运算,并通过lcd进行显示。

实验描述:
1》该数据是一个只读数据,并不会被修改。
2》该数据出现在2个地方:1》定时时间为1秒的l中断服务函数中(通过snprintf()将该数据转换为字符串送给lcd显示)。 2》while(1)计算函数中(该数据仅仅作为右值参与计算)。

实验现象:
lcd显示该数据现象为:随机情况下正确,随机情况为0(我通过串口printf()该数据现象也是如此)。

调试经过:
前面的各种debug过程我就略过。最终我考虑到是否为函数重入问题。以下是我的解决办法:
使用MDK自带的microLIB库中的snprintf()取代defaultC库中的snprintf()。问题最终解决。

请教问题:
问题虽然解决,但是我感觉还有很多疑惑,如下:
1》如何查找snprintf()在defaultC下的源码,难道defaultC库并不确保所有库函数都是可重入的?microLIB中的所有库函数确保都是可重入的?
2》microLIB和defaultC还有哪些差别(下图是MDK手册对microLIB的相关说明,其中根本没有提到reentrant相关问题)?
000.png (16.22 KB, 下载次数: 0) 下载附件 2018-3-12 12:53 上传
恳请大神指教,不胜感激!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
16条回答
security
1楼-- · 2019-12-21 18:17
从你的实验数据来看,只能是猜测:
microlib 和 标准的 lib,是两套不同的实现。而标准的 lib 的实现更新、更严格。

还是一起期待大神的更专业的解答吧。
love_ourdev
2楼-- · 2019-12-21 20:24
CCR的STKALIGN功能,只是用硬件来保证了中断或异常上下文的堆栈8字节对齐而已。而带有OS的用户线程是享受不到这个硬件保障的!
如果你的线程创建时,堆栈指针不是指向8字节对齐地址,或者是调用汇编实现的代码并且该代码并没有遵守8字节来处理栈指针时,就会悲剧的。
如果你碰到这种现象:同样的代码重新编译,或者随便改改重新编译,总是时好时坏。那就是堆栈对齐问题导致的。
重新编译时链接器会重新分配各种数据的内存地址,这就造成了时好时坏的现象。
laoshuhunya
3楼-- · 2019-12-21 21:02
 精彩回答 2  元偷偷看……
love_ourdev
4楼-- · 2019-12-22 00:08
具体我也不细说了,给你个截图吧。网上查一查比在坛里一问一答这样一来一去省很多时间。

2018-03-13_115345.png (108.63 KB, 下载次数: 0)

下载附件

2018-3-13 11:55 上传

擦鞋匠
5楼-- · 2019-12-22 05:23
security 发表于 2018-3-13 11:15
我想这个问题,你去查阅一下双字栈对齐的历史变迁,或许可以窥视一二。
后面的版本,都是默认打开的。编 ...

感谢security大神的精彩回复。

的确如阁下所言,既然后续版本硬件都已经默认开启该特性,那么后续版本的编译器自然不需要增加所谓的“额外”代码。

不过我个人觉得:microLIB应该比stardardLIB更加严格才对,否则,弄个microLIB不是“自取其辱”嘛?恳请指教!
擦鞋匠
6楼-- · 2019-12-22 06:53
laoshuhunya 发表于 2018-3-13 11:45
问题1》通过使用microLIB库解决该问题,我还能做到“自圆其说”,为什么开启栈双字对齐也能解决该问题呢 ...

感谢laoshuhunya精彩回复。

大神的回答解释了我心中的一个疑惑。疑惑如下:

之前版本我是在while(1)中调用snprintf(),没有遇到此问题。后来,我决定在定时器中断服务函数中调用snprintf(),因此遇到此问题。

可见:如果不开启双字对齐特性:对于中断栈帧,硬件和编译器是不会对此作出保证的。

但是:函数调用能确保每次调用都是8字节对齐嘛(我随意查看了某个函数调用,共消耗8个字节,倒的确是8字节对齐)?这也是某个ARM标准?

一周热门 更多>