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).
程序老是有这种错误,有时候改来改去又没了,加了新函数又出来了,又不知如何解决,真烦!
说明:我的程序中并没有过多的嵌套调用啊 这么厉害的, 48K程序只用了100个DATA,XDATA 0
牛的.你中断里是不是调用了这个函数 其实我没有用到很多中断,只开了串口中断和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).
现在我还是糊里糊涂的,弄不清 我的感觉是它警告你有些函数没有被调用,我以前也遇到过类似的,不是很记得了 好像是函数有递归调用,例如:
自递归
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的地址和大小,详细该文件) 4楼正解
设计时需注意,防止堆栈溢出。
可使用一全局变量做标志,限制递归嵌套的层数。 自从把那几个函数加了"reentrant"之后,再也没出现过那个警告了,警告和错误都为0,而且现在程序有50多K了,运行很正常.
非常感谢4楼!又学到了很多,谢谢! 相同的错误提示,但我碰到的情况似乎不是楼上各位所说的原因造成的,情况如下:
第一处:把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; 局部变量没有初使化使用的话会有警告的
全局变量不会,好象全局变量如果你不赋值是默认初使化成0的 函数重入问题 我是在用函数指针调用函数时遇到这样的问题,我确认我的代码没有递归调用,也没有不合理的调用。
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
===========================================================================
修改原因:纠结源链接中。 遇到相同问题,感谢hecat。 mark mark *** 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中没有使用过这二个函数,还请路过的高手指点指点! 4楼给力! mark 函数没调用,应该没什么问题。不行就把没调用的函数屏蔽了。 MARK 就如4楼所说 keil用久了自然也知道原因了就是中断函数递归调用 哎呀,我的是8楼的情况,8楼你真帅
页:
[1]