Keil C51​​​​​​​中函数指针使用注意事项 

Keil C51中函数指针使用注意事项 

 

在C51 中,结构体成员采用函数指针后,发现main函数中局部变量的值被修改,开始以为堆栈溢出,后发现,单片机使用函数指针会使得调用树出错,在帮助文档中,搜索 function pointer 中,note 指明

Note:

 Because of the limited stack space of the 8051, the linker overlays function variables and arguments in memory. When you use a function pointer, the linker cannot correctly create a call tree for your program. For this reason, you may have to correct the call tree for the data overlaying. Use the OVERLAY directive with the linker to do this.

 官方告诉你会出错。

 

然后才知道,单片机不把函数参数和局部变量放入堆栈中,,,如下内容

以下摘自:https://wenku.baidu.com/view/64fa24e46137ee06eef91812.html 

内容如下

 

当函数指针用在Keil C51中时,一定要注意编译器自动生成的函数调用树通常是不正确的,需要手动调整。否则可能造成无法预知的后果。 这是因为,Keil C51编译器并不把函数参数和局部变量压入堆栈中,而是放在寄存器或固定的内存位置

C51的编译器监视函数调用的嵌套顺序,把几个函数的变量放在同样固定的位置。在C51编译器中连接器会搜索所有函数中变量占用存储区间最多的函数,然后以这个函数的变量的占用空间开辟一片空间,其他函数的变量也放在该空间中,同时实现了变量的覆盖(无相互调用)与地址的共享。

例如函数A占10个字节,函数B占20个字节,函数C占15个字节,如果它们之间没有相互调用则仅需20个字节就可以满足45个字节的变量需要。 正是由于所有函数的参数和局部变量的共享一个覆盖区,函数没有相互的调用时,在执行一个函数时,会将另一个函数的变量的存储区覆盖。如果函数有调用,那么不会覆盖原来函数的局部变量的区间

调用树(call tree)是由Keil链接器自动生成的,用于描述函数的调用关系(调用树可通过编译生成的*.M51(.map)文件的OVERLAY MAP OF MODULE部分查看,该部分详细的说明了函数的调用关系以及对覆盖存储区的使用情况。

链接器通过分析调用树来确定哪些寄存器或内存位置是可安全覆盖的。这样两个不同时调用的函数就可以共享同一块内存用于传递参数和存储局部变量。

但对于函数指针来说,编译器并不知道函数指针将指向哪个函数。这导致了调用树构造出错的可能,函数的参数和局部变量也可能被错误覆盖(例如,函数A通过函数指针调用了函数B,但编译器并不知道它们之间存在调用关系,所以认为它们是可以共享同一块内存的。这样当函数A调用了函数B,回到函数A后,函数A的参数和局部变量可能已经被改变了,再往下运行就出错了)。 对此,Keil提供了链接器OVERLAY伪指令,可让用户自行修改调用树,调整函数的调用关系。

OVERLAY(?PR?_FUNC?DMAIN ~ (?PR?_FUNC_A?DMAIN,?PR?_FUNC_B?DMAIN)) 
     意思是从FUNC函数中删除对FUNC_A和FUNC_B的调用。 

OVERLAY(?PR?_MAIN?DMAIN ! (?PR?_FUNC_A?DMAIN,?PR?_FUNC_B?DMAIN)) 
     意思是添加FUNC函数对FUNC_A和FUNC_B的调用。 

Keil集成开发环境中,在“BL51 Misc”-“Overlay”中填入中的内容。 

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值