打印
[程序源码]

Keil 使用函数指针的错误内存优化

[复制链接]
2131|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
秉烛良宵|  楼主 | 2015-7-19 15:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
      在调试FAT32的程序代码时发现一个很奇怪的问题,有个函数的形参是函数指针,每次用这个函数都会出错。查看汇编发现了问题所在,下面用一段简单的代码测试自己的发现。望请高手指正!
#include<STC12C5A.h>
#include<stdio.h>

/**************************************************************************
- 功能描述:51单片机的串口初始化
- 参数说明:无
- 返回说明:无
- 注:2400bps@24.000MHz
**************************************************************************/
void UartInit(void)
{
PCON &= 0x7F;  //波特率不倍速
SCON = 0x50;  //8位数据,可变波特率
AUXR &= 0xFB;  //独立波特率发生器时钟为Fosc/12,即12T
BRT = 0xF3;  //设定独立波特率发生器重装值
AUXR |= 0x01;  //串口1选择独立波特率发生器为波特率发生器
AUXR |= 0x10;  //启动独立波特率发生器
TI = 1;   //使用Printf函数时要有这一句
}
void TEST(unsigned long tmp)
{
if(tmp<10)
tmp++;
printf("tmp=%ld\n",tmp);
}
void fun(unsigned long len,void (*pfun)(unsigned long))
{
unsigned long t;

if(len>20)
  t = 10;
else
  t = 5;
while((--len)>10)
  pfun(t);
}
void main()
{
UartInit();
TEST(5000);
fun(0xFEFE,TEST);
while(1);
}
按照常理这个程序烧写到单片机中应该是不断发送出“tmp=10”,但是结果不是这样,看下汇编才能明白


变量len的寄存器被变量tmp用了,优化级数为1时才能避免这个结果。


这是优化级数大于1的输出

这是优化级数为1的输出







相关帖子

沙发
airwill| | 2015-7-19 22:22 | 只看该作者
编译器优化的情况.
不过通常情况下编译器优化不会导致问题, 楼主看到这个是两个变量放到了相同的地址了, 会导致数据覆盖, 这是 C51 特殊的局部变量处理方式, 原因是 mcs51 过小的 RAM 和效率低下的堆栈操作, 局部变量被放在了 RAM 里而不是堆栈里, 效率大为提高, 为了节省 RAM, 编译器会进行覆盖分析来高效利用 RAM 空间, 就是楼主看到情况.
为此, 楼主要特别注意变量的作用域.

使用特权

评论回复
板凳
beebeecici| | 2015-7-19 22:23 | 只看该作者
fun(0xFEFE,TEST);

TEST函数不要实参吗?

使用特权

评论回复
地板
秉烛良宵|  楼主 | 2015-7-19 23:55 | 只看该作者
beebeecici 发表于 2015-7-19 22:23
fun(0xFEFE,TEST);

TEST函数不要实参吗?

那个是指针,TEST的地址

使用特权

评论回复
5
ayb_ice| | 2015-7-20 08:01 | 只看该作者
要看编译时有没有警告,有的话要分析警告的原因

使用特权

评论回复
6
秉烛良宵|  楼主 | 2015-7-20 15:22 | 只看该作者
ayb_ice 发表于 2015-7-20 08:01
要看编译时有没有警告,有的话要分析警告的原因

程序很简单,逻辑上是没有错的,其他编译器编译可以正常,包括用经典的C编译器在电脑运行的是正常的。

使用特权

评论回复
7
ayb_ice| | 2015-7-20 16:44 | 只看该作者
秉烛良宵 发表于 2015-7-20 15:22
程序很简单,逻辑上是没有错的,其他编译器编译可以正常,包括用经典的C编译器在电脑运行的是正常的。 ...

KEIL C51的很多特性与标准C是不同的,默认是不支持递归和重入的,主要表现在局部变量是静态分配的,不是通过堆栈分配的

所以对于函数指针类应用要注意,可能不太正常

使用特权

评论回复
8
秉烛良宵|  楼主 | 2015-7-21 16:09 | 只看该作者
嗯, 是的,网上查了下发现这个问题有很多**都在谈论,解决的方法是手动修改调用树 Keil C51中函数指针的使用.pdf (110.49 KB)



使用特权

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

本版积分规则

26

主题

163

帖子

7

粉丝