当前位置:首页 > 技术心得 > 正文内容

BL51: WARNING L13 (RECURSIVE CALL TO SEGMENT) WITH CONSTANTS 解决

xjtudll9年前 (2018-04-21)技术心得18660

问题描述:

 

将函数名存储在table里,通过函数指针的方式调用函数。

编译提示:

BL51: WARNING L13 (RECURSIVE CALL TO SEGMENT) WITH CONSTANTS

使用环境:

C51 Version 7.00

代码例程(使用Keil官方资料来说明):

文件名是:EXAMPLE1.C

void func1 (unsigned char *msg) {

  ;

}

void func2 (void) {

  unsigned char uc;

  func1("xxxxxxxxxxxxxxx");

}

code void (*func_array[])() = { func2 };

void main( void ) {

  (*func_array[0])();

}

编译的时候就会提示:

*** WARNING 13: RECURSIVE CALL TO SEGMENT

SEGMENT: ?CO?EXAMPLE1

CALLER: ?PR?FUNC2?EXAMPLE1

原因:

In this program example, func2 defines a constant string ("xxx...xxx") which is located in the constant code segment ?CO?EXAMPLE1. The definition:

code void (*func_array[])() = { func2 };

generates a reference between segment ?CO?EXAMPLE1 (where the code table is located) and the executable code segment ?PR?FUNC2?EXAMPLE1. Since func2 also refers to segment ?CO?EXAMPLE1, BL51 assumes that there is a recursive call.

官方的解决办法:

RESOLUTION

To avoid this problem, you must manually remove the reference between func2 and the ?CO?EXAMPLE1 segment. The following overlay directive does that:

bl51 EXAMPLE1.OBJ IX OVERLAY (?CO?EXAMPLE1 ~ FUNC2, MAIN ! FUNC2)

?CO?EXAMPLE1 ~ FUNC2 deletes the implied call reference between func2 and the code constant segment in the example. Then, MAIN ! FUNC2adds a reference between MAIN and FUNC2. This is required because main calls func2 indirectly. Note that automatic overlay analysis does not allow for references made to functions via pointers. References of this type must be manually implemented, as in the example above.

另一个办法:

将code void (*func_array[])() = { func2 }; 放在另一个C文件里,这样就规避了所谓的递归调用了。

 

参考文献:

http://www.keil.com/support/docs/2379.htm

http://blog.csdn.net/avideointerfaces/article/details/32687899

扫描二维码推送至手机访问。

版权声明:本文由鸟的天空发布,如需转载请注明出处。

本文链接:http://www.xjtudll.cn/Exp/497/

标签: keil
分享给朋友:

“BL51: WARNING L13 (RECURSIVE CALL TO SEGMENT) WITH CONSTANTS 解决” 的相关文章

清理金蝶用户异常登录信息SQL语句

重点:删除 t_userprofile 表中某用户的信息 1. 打开帐套管理,找到该帐套,备份帐套 备份完帐套后, ,选中该帐套,然后点属性,在帐套属性里复制数据库实体名 2.在电脑开始程序里打开查询分析器 直接点确定进入 在查询框里输入 use,然后将复制的数据库实体名粘贴其后面,中间要有空白,...

如何释放由RingtoneManage实例化的MediaPlayer

参考资料:http://stackoverflow.com/questions/15450255/how-to-release-the-mediaplayer-instantiated-by-ringtonemanager 为了获取android铃声的名称,使用了以下代码 //根据铃声地址获取铃声的...

Multisim运放输出超过电源电压解决

Multisim运放输出超过电源电压解决

在使用Multisim自带库里的运放的时候,例如LM324M,发现一个问题,运放的输出电压能达到几百V甚至几千V,而电源明显只有几V而已。输出电压超过电源电压,理论上是不可能的,实际上也是不可能的,那么肯定就是仿真有误了,其实根本原因是Multisim里面运放是三脚模型,根本没考虑电源。我们查看LM...

服务端把客户端几次发的数据一起接受了,是怎么回事?

服务端把客户端几次发的数据一起接受了,是怎么回事?

  客户端是android,服务端是c#,手机监听手指一动就把手指所在的那个点的位置发给服务端,服务端死循环接收,android可以保证一次是给服务端发一条数据,但是服务端把几次发的数据一起接受了 原因: 因为TCP是流式数据,没有次的概念。看题主的数据,结构本身比较简单,可以试试利用...

C语言交换两个数

可能大家都认为交换两个数如此的简单,没必要写,没新意。例如,交换a和b两个数,教科书上一直这样写: temp=b; a=temp; b=a; 确实很简单。但是最近看到一段代码,觉得十分高超,是这样的: a^=b; b^=a; a^=b; 同样也是三句代码,但是却未...

水晶报表 跳过打印预览,直接打印

不要用 CrytalReportViewer1.ReportSource=myReport; 直接myReport.PrinttoPrinter(1,true/false,0,0); 重点就是这个PrintToPrinter函数...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。