C 如何为局部变量';谁在嵌入式系统中工作?

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(

我们正在使用ccrx编译器embOS RTOS 代码中有一个函数

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约束目标。这不仅取决于这些,还取决于整个代码。单个添加/删除的变量可能会改变