wyb4993 发表于 2008-7-18 13:19:37

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

如下:

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).

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

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

zxw103 发表于 2008-7-18 14:28:21

这么厉害的, 48K程序只用了100个DATA,XDATA 0
牛的.你中断里是不是调用了这个函数

wyb4993 发表于 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).

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

jmpxwh 发表于 2008-7-20 09:41:34

我的感觉是它警告你有些函数没有被调用,我以前也遇到过类似的,不是很记得了

shark 发表于 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的地址和大小,详细该文件)

xuhai777 发表于 2008-7-20 12:28:28

4楼正解
设计时需注意,防止堆栈溢出。
可使用一全局变量做标志,限制递归嵌套的层数。

wyb4993 发表于 2008-7-22 18:14:35

自从把那几个函数加了"reentrant"之后,再也没出现过那个警告了,警告和错误都为0,而且现在程序有50多K了,运行很正常.

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

yangxin4658 发表于 2009-8-19 12:21:58

相同的错误提示,但我碰到的情况似乎不是楼上各位所说的原因造成的,情况如下:
第一处:把VOL数组的定义放在函数体内就警告,放到外面就没事了。
unsigned char vol;
void SetVol()
{
//        unsigned char vol;//有点搞不明白的是,这个数组的定义为什么就不能放在函数内呢,而第二处却可以。
        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;//={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 无警告
        unsigned charchr,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;

lusson 发表于 2010-1-21 22:51:13

局部变量没有初使化使用的话会有警告的
全局变量不会,好象全局变量如果你不赋值是默认初使化成0的

amazing030 发表于 2010-1-22 17:45:36

函数重入问题

hecat 发表于 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)();
}
这样会提示:
*** 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)();}

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

povoss 发表于 2010-7-23 10:23:06

遇到相同问题,感谢hecat。

sunchao151 发表于 2010-11-1 11:34:55

mark

sunchao151 发表于 2010-11-1 12:09:40

mark

xjjiang 发表于 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中没有使用过这二个函数,还请路过的高手指点指点!

forever37 发表于 2010-12-17 00:05:55

4楼给力!

muzheyun 发表于 2011-1-20 15:33:10

mark

proteldxp 发表于 2011-1-23 10:37:13

函数没调用,应该没什么问题。不行就把没调用的函数屏蔽了。

CHENXIAOTIAN 发表于 2011-1-23 10:55:13

MARK

xiaobendan 发表于 2011-1-23 12:59:52

就如4楼所说

linyu0395 发表于 2011-1-23 13:59:05

keil用久了自然也知道原因了就是中断函数递归调用

yunmenghan 发表于 2014-11-3 09:14:35

哎呀,我的是8楼的情况,8楼你真帅
页: [1]
查看完整版本: keil c51警告:*** WARNING L13: RECURSIVE CALL TO SEGMENT,如何解决?