C 如何为局部变量';谁在嵌入式系统中工作?
我们正在使用ccrx编译器embOS RTOS 代码中有一个函数C 如何为局部变量';谁在嵌入式系统中工作?,c,embedded,rtos,C,Embedded,Rtos,我们正在使用ccrx编译器embOS RTOS 代码中有一个函数 void fun( ) { if(condition) { int a;} else if(condition1) {int b;}............ else { int z;} } 每当调用该函数时,相关线程堆栈就会溢出。如果很少对int变量声明进行注释,则线程堆栈不会溢出 堆栈是如何分配的?在一个条件成功后,内存不会被分配吗 让我们以GCC为例 void fun(
void fun( )
{
if(condition)
{ int a;}
else if(condition1)
{int b;}............
else
{ int z;}
}
每当调用该函数时,相关线程堆栈就会溢出。如果很少对int变量声明进行注释,则线程堆栈不会溢出
堆栈是如何分配的?在一个条件成功后,内存不会被分配吗 让我们以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
即使没有优化,这些变量也是死代码和优化出来的
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
给
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
00000000:
0:e59f2030 ldr r2,[pc,#48];38
4:E592300LDR r3[r2]
8:e2833001添加r3,r3,#1
c:e353000a cmp r3,#10
10:e5823000 str r3[r2]
14:da000001表20
18:e3a00001 mov r0,#1
1c:E12FF1E bx lr
20:e92d4010推送{r4,lr}
24:ebfffffe bl 0
28:e2900000加上r0,r0,#0
2c:13a00001移动r0,#1
30:e8bd4010 pop{r4,lr}
34:E12FF1E bx lr
38:00000000安第克r0,r0,r0
bss部分的拆卸:
00000000 :
0:00000000安第克r0,r0,r0
它是一个局部变量,但由于是静态的,它进入全局池,不像其他局部变量那样在堆栈上分配(或优化到寄存器)
虽然有趣的是,这是一个它没有立即在堆栈上分配的情况,虽然在这种情况下这是好的,但如果不需要的话,不要用递归来加重堆栈的负担。很好的优化
没有理由假设堆栈指针会在整个函数中多次更改,因为您在高级语言中所做的操作。我的猜测是,这使得开发编译器更容易在一次开发之前完成所有工作,尽管这会浪费内存。另一方面,因为你去会花费更多的指令(空间和时间)。让我们以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
即使没有优化,这些变量也是死代码和优化出来的
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
给
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
00000000:
0:e59f2030 ldr r2,[pc,#48];38
4:E592300LDR r3[r2]
8:e2833001添加r3,r3,#1
c:e353000a cmp r3,#10
10:e5823000 str r3[r2]
14:da000001表20
18:e3a00001 mov r0,#1
1c:E12FF1E bx lr
20:e92d4010推送{r4,lr}
24:ebfffffe bl 0
28:e2900000加上r0,r0,#0
2c:13a00001移动r0,#1
30:e8bd4010 pop{r4,lr}
34:E12FF1E bx lr
38:00000000安第克r0,r0,r0
bss部分的拆卸:
00000000 :
0:00000000安第克r0,r0,r0
它是一个局部变量,但由于是静态的,它进入全局池,不像其他局部变量那样在堆栈上分配(或优化到寄存器)
虽然有趣的是,这是一个它没有立即在堆栈上分配的情况,虽然在这种情况下这是好的,但如果不需要的话,不要用递归来加重堆栈的负担。很好的优化
没有理由假设堆栈指针会在整个函数中多次更改,因为您在高级语言中所做的操作。我的猜测是,这使得开发编译器更容易在一次开发之前完成所有工作,尽管这会浪费内存。另一方面,这样做会花费更多的指令(空间和时间)。我对ccrx编译器不太了解,但您肯定可以查看反汇编列表,看看
a
,b
,和z
在if分支中有条件地分配,或在函数开头分配所有。@David Grayson感谢您的建议。我没有任何用于我正在工作的系统的调试器。反汇编与调试不同。您需要一个反汇编程序或调试器。许多编译器不需要反汇编就可以输出汇编。@David Grayson好的。我将检查调用函数时如何分配内存是非常系统特定的。无论函数如何执行,编译器都可能分配堆栈帧。或者它可能根本不使用堆栈,而是使用CPU寄存器。为了知道在您的情况下会发生什么,您必须阅读反汇编和/或编译器手册。不过,了解堆栈溢出为什么出现在这个特定函数中可能不是特别有趣。首先,您需要关注为什么会出现堆栈溢出。堆栈大小需要有更好的边距。我对ccrx编译器不太了解,但您肯定可以查看反汇编列表,看看a
、b
和z
是否有条件地分配在if分支中,还是全部分配在函数的开头。@David Grayson感谢您的建议。我没有任何用于我正在工作的系统的调试器。反汇编与调试不同。您需要一个反汇编程序或调试器。许多编译器不需要反汇编就可以输出汇编。@David Grayson好的。我将检查调用函数时如何分配内存是非常系统特定的。无论函数如何执行,编译器都可能分配堆栈帧。或者它可能根本不使用堆栈,而是使用CPU寄存器。为了知道在您的情况下会发生什么,您必须阅读反汇编和/或编译器手册。不过,了解堆栈溢出为什么出现在这个特定函数中可能不是特别有趣。首先,您需要关注为什么会出现堆栈溢出。堆栈大小需要有更好的边距。我在一些4。x或5。x版本选项中添加了一个弱内存GCC来考虑RAM约束目标。这不仅取决于这些,还取决于整个代码。单个添加/删除的变量可能会改变