搜索
bottom↓
回复: 21

keil c51警告:*** WARNING L13: RECURSIVE CALL TO SEGMENT,如何解决?

[复制链接]

出0入0汤圆

发表于 2008-7-18 13:19:37 | 显示全部楼层 |阅读模式
如下:

Build target 'Target 1'
compiling main.c...
linking...
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MAIN
    CALLER:  ?PR?_DISPLAY?MAIN
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MAIN
    CALLER:  ?PR?_LCD_BMP_WR?MAIN
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MAIN
    CALLER:  ?PR?_SHUZI8?MAIN
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MAIN
    CALLER:  ?PR?_SHUZI?MAIN
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MAIN
    CALLER:  ?PR?_GRAHDISP?MAIN
Program Size: data=100.1 xdata=0 code=48655
creating hex file from "ADC"...
"ADC" - 0 Error(s), 5 Warning(s).

程序老是有这种错误,有时候改来改去又没了,加了新函数又出来了,又不知如何解决,真烦!

说明:我的程序中并没有过多的嵌套调用啊

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2008-7-18 14:28:21 | 显示全部楼层
这么厉害的, 48K程序只用了100个DATA,XDATA 0
牛的.你中断里是不是调用了这个函数

出0入0汤圆

 楼主| 发表于 2008-7-18 14:56:55 | 显示全部楼层
其实我没有用到很多中断,只开了串口中断和T0中断.我怀疑全局变量和局部变量搞混了,变量一多就分不清了.

在网上找了资料,现在把以上几个函数定义为:reentrant,现在没有警告了:

Build target 'Target 1'
compiling main.c...
linking...
Program Size: data=100.1 xdata=0 code=48932
creating hex file from "ADC"...
"ADC" - 0 Error(s), 0 Warning(s).

现在我还是糊里糊涂的,弄不清

出0入0汤圆

发表于 2008-7-20 09:41:34 | 显示全部楼层
我的感觉是它警告你有些函数没有被调用,我以前也遇到过类似的,不是很记得了

出0入0汤圆

发表于 2008-7-20 10:16:53 | 显示全部楼层
好像是函数有递归调用,例如:


自递归
void foo(int someparameter)
{
   if (...)
   {
      foo(otherparameter);
   }
}

或交叉递归

void f(int a)
{
   if (...)
   {
       g(a);
   }

}


void g(int b)
{
    if (...)
    {
        f(b+4);
    }
}


因为Keil C的局部变量默认不是在栈上分配的,而是没有嵌套调用的函数是共用变量空间(实际是全局空间)来存储局部变量和函数参数,在递归调用的时候上一层次的局部变量会被本层次调用冲掉,加关键字reentrant让keil为该函数的局部变量和形参在栈上分配内存。(可能要修改startup.a51启动代码设定reentrant的地址和大小,详细该文件)

出0入0汤圆

发表于 2008-7-20 12:28:28 | 显示全部楼层
4楼正解
设计时需注意,防止堆栈溢出。
可使用一全局变量做标志,限制递归嵌套的层数。

出0入0汤圆

 楼主| 发表于 2008-7-22 18:14:35 | 显示全部楼层
自从把那几个函数加了"reentrant"之后,再也没出现过那个警告了,警告和错误都为0,而且现在程序有50多K了,运行很正常.

非常感谢4楼!又学到了很多,谢谢!

出0入0汤圆

发表于 2009-8-19 12:21:58 | 显示全部楼层
相同的错误提示,但我碰到的情况似乎不是楼上各位所说的原因造成的,情况如下:
第一处:把VOL数组的定义放在函数体内就警告,放到外面就没事了。
unsigned char vol[2];
void SetVol()
{
//        unsigned char vol[2];  //有点搞不明白的是,这个数组的定义为什么就不能放在函数内呢,而第二处却可以。
        gb_RunMenuProg=0;        //不连续执行
        ClearLEDxy(2,0,128,48);
        DisplayString(2,0x20,"本机音量:",0);
        InputString(4,0x40,vol,1);
}
第二处:
//;*****************************************************************
//;* 子程序名:        InputString
//;* 功能描述:        输入一串字符,并在指定位置回显。
//;*            
//;* 入口参数:        Row:行号;Col:列号;string:字符串指针;len:字符数
//;* 局部变量:        chr,number:临时字符缓冲区;i:计数用
//;* 出口参数:        string:新输入的字符由它返回。
//;* 建立日期:        2009.8.18
//;* 创 建 者:        杨 鑫
//;* 更新日期:       
//;* 修 改 者:
//;*****************************************************************

void InputString(unsigned char Row,unsigned char Col,unsigned char *string,unsigned char len) //reentrant
{    //数组定义在函数体内,不在定义时赋初值就不会警告。加上reentrant 或是把定义和赋初值放到外面,警告也会没有。
        //unsigned char number[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 有警告
        unsigned char number[20];//={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 无警告
        unsigned char  chr,i;
        for(i=0;i<len;i++)
        {
                number=string;
        }
        for(i=0;i<len;i++)
        {
                if(number!='.')break;
        }
        DisplayString(Row,Col,string,0);
        while(1)
        {
                if(i<len) if(0!=(chr=InputChar(Row,Col+(6*i)))) number=chr
                if(gb_FcuPressEvent)
                {
                        gb_FcuPressEvent=0;
                        switch(gcu_FcuKey)
                        {
                        case KEY_ESC:
                                gb_FcuPressEvent=1;
                                return;
                                break;

出0入54汤圆

发表于 2010-1-21 22:51:13 | 显示全部楼层
局部变量没有初使化使用的话会有警告的
全局变量不会,好象全局变量如果你不赋值是默认初使化成0的

出0入0汤圆

发表于 2010-1-22 17:45:36 | 显示全部楼层
函数重入问题

出0入25汤圆

发表于 2010-7-1 11:38:09 | 显示全部楼层
我是在用函数指针调用函数时遇到这样的问题,我确认我的代码没有递归调用,也没有不合理的调用。

google了一下,按照网友的经验,把函数表独立成一个c文件,解决了这个问题,现在贴出来,也许对大家有帮助。

原链接:http://blog.21ic.com/user1/6121/archives/2010/66044.html

===========================================================================
Keil "RECURSIVE CALL TO SEGMENT"彻底解决2010-1-5 2:42:00
我们在做菜单程序或通过函数指针调用函数时,如果被调用的函数中有包含了常量字符串,那么经常会出现这样的的错误提示:"RECURSIVE CALL TO SEGMENT"意思是"递归调用段",如何解决呢,之前我没有找到很好的方法,这段时间我回过头来看keil的datasheet,找到了解决方法,当然keil手册提供的解决方法是编写一个.lin文件,我觉得麻烦,现提供我的解决方法,实例还是用keil提供的那个实例:

#pragma code symbols debug oe

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
我的解决方法是:
把code void (*func_array[])() = { func2 };放在另外一个段,
即另外一个.c文件中也就不存在同一个段递归调用情况,如下:
keilrecur.c文件
#i nclude <reg51.h>
void func2( void );
extern code void (*func_array[])();
void func1(unsigned char *msg ) {  msg=msg; }
void func2( void ) {  unsigned char uc;  uc=uc;  func1("xxxxxxxxxxxxxxx");}

void main( void ) {  (*func_array[0])();}

funcptr.c文件
#i nclude <reg51.h>
void func2( void );code void (*func_array[])() = { func2 };
这样就可以解决段递归问题.
我们在做LCD菜单时,喜欢做一个KeyTab,这样也会出现"递归调用段"情况,
那么我们可以把KeyTab单独作为.c文件,方便管理又可以避免这种错误提示.
             加速度 Jan.5.2010
===========================================================================
修改原因:纠结源链接中。

出0入0汤圆

发表于 2010-7-23 10:23:06 | 显示全部楼层
遇到相同问题,感谢hecat。

出0入0汤圆

发表于 2010-11-1 11:34:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-1 12:09:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-27 19:26:39 | 显示全部楼层
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MEMU
    CALLER:  ?PR?POP?SYSTEMSET_COMMON
*** WARNING L13: RECURSIVE CALL TO SEGMENT
    SEGMENT: ?CO?MEMU
    CALLER:  ?PR?ONE_NUMBER_1_8_INPUT?1_8_INPUT

我在使用菜单时也遇到了这种情况,但按键的KEYTAB重新定义为C文件,也有这个问题,但想不通的是在KEYTAB中没有使用过这二个函数,还请路过的高手指点指点!

出0入0汤圆

发表于 2010-12-17 00:05:55 | 显示全部楼层
4楼给力!

出0入0汤圆

发表于 2011-1-20 15:33:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-23 10:37:13 | 显示全部楼层
函数没调用,应该没什么问题。不行就把没调用的函数屏蔽了。

出0入0汤圆

发表于 2011-1-23 10:55:13 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-1-23 12:59:52 | 显示全部楼层
就如4楼所说

出0入0汤圆

发表于 2011-1-23 13:59:05 | 显示全部楼层
keil用久了  自然也知道原因了  就是中断函数递归调用

出0入0汤圆

发表于 2014-11-3 09:14:35 | 显示全部楼层
哎呀,我的是8楼的情况,8楼你真帅
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 03:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表