我们正在使用ccrx编译器,embOS RTOS 代码中有一个函数,
void fun( )
{
if(condition)
{ int a;}
else if(condition1)
{int b;}............
else
{ int z;}
}
每当调用该函数时,相关的线程堆栈都会溢出。如果很少有int变量声明被注释,则线程堆栈不会溢出。
如何分配堆栈?条件成功后是否分配了内存?
答案 0 :(得分:2)
让我们以GCC为例
void fun( int condition, int condition1 )
{
if(condition)
{ int a; a=5;}
else if(condition1)
{int b; b=7;}
else
{ int z; z=9; }
}
并选择一个目标,而不是为了获得ccrx而支付任何费用......
00000000 <fun>:
0: e52db004 push {r11} ; (str r11, [sp, #-4]!)
4: e28db000 add r11, sp, #0
8: e24dd01c sub sp, sp, #28
c: e50b0018 str r0, [r11, #-24] ; 0xffffffe8
10: e50b101c str r1, [r11, #-28] ; 0xffffffe4
14: e51b3018 ldr r3, [r11, #-24] ; 0xffffffe8
18: e3530000 cmp r3, #0
1c: 0a000002 beq 2c <fun+0x2c>
20: e3a03005 mov r3, #5
24: e50b3008 str r3, [r11, #-8]
28: ea000007 b 4c <fun+0x4c>
2c: e51b301c ldr r3, [r11, #-28] ; 0xffffffe4
30: e3530000 cmp r3, #0
34: 0a000002 beq 44 <fun+0x44>
38: e3a03007 mov r3, #7
3c: e50b300c str r3, [r11, #-12]
40: ea000001 b 4c <fun+0x4c>
44: e3a03009 mov r3, #9
48: e50b3010 str r3, [r11, #-16]
4c: e1a00000 nop ; (mov r0, r0)
50: e28bd000 add sp, r11, #0
54: e49db004 pop {r11} ; (ldr r11, [sp], #4)
58: e12fff1e bx lr
没有分配
void fun( int condition, int condition1 )
{
if(condition)
{ int a;/* a=5;*/}
else if(condition1)
{int b;/* b=7;*/}
else
{ int z; /*z=9;*/ }
}
即使没有优化,这些变量也是死代码并且已经过优化
00000000 <fun>:
0: e52db004 push {r11} ; (str r11, [sp, #-4]!)
4: e28db000 add r11, sp, #0
8: e24dd00c sub sp, sp, #12
c: e50b0008 str r0, [r11, #-8]
10: e50b100c str r1, [r11, #-12]
14: e1a00000 nop ; (mov r0, r0)
18: e28bd000 add sp, r11, #0
1c: e49db004 pop {r11} ; (ldr r11, [sp], #4)
20: e12fff1e bx lr
堆栈上有一些字节用于对齐,它们可能已经削减了一些并保持对齐但这是另一个主题。
这里的要点是因为在高级语言中你的变量只用在函数的一部分中并不意味着编译器必须这样做,编译器肯定是gcc,倾向于完成所有的堆栈分配在函数的开头和最后的清理。就像在这里做的那样......
这与
不同int fun( void )
{
static int x;
x++;
if(x>10) return(1);
if(fun()) return(1);
return(0);
}
给出了
00000000 <fun>:
0: e59f2030 ldr r2, [pc, #48] ; 38 <fun+0x38>
4: e5923000 ldr r3, [r2]
8: e2833001 add r3, r3, #1
c: e353000a cmp r3, #10
10: e5823000 str r3, [r2]
14: da000001 ble 20 <fun+0x20>
18: e3a00001 mov r0, #1
1c: e12fff1e bx lr
20: e92d4010 push {r4, lr}
24: ebfffffe bl 0 <fun>
28: e2900000 adds r0, r0, #0
2c: 13a00001 movne r0, #1
30: e8bd4010 pop {r4, lr}
34: e12fff1e bx lr
38: 00000000 andeq r0, r0, r0
Disassembly of section .bss:
00000000 <x.4089>:
0: 00000000 andeq r0, r0, r0
它是一个局部变量但通过静态进入全局池,不像其他局部变量那样在堆栈上分配(或优化为寄存器)。
虽然有趣的是,这是一个不立即在堆栈上分配的情况,虽然在这种情况下这是好的,但如果你不需要,不要用递归加载堆栈。很好的优化。
由于您在高级语言中所做的事情,没有理由认为堆栈指针会在整个函数中多次更改。我的猜测是,即使在内存上浪费,开发编译器也更容易一次性完成。另一方面,当你去的时候会花费更多的指令(空间和时间)。