Why is the "stack" sacred from embedded programming?

Follow, star public account, direct access to exciting content

ID: Technology makes dreams greater

Author: Li Xiao Yao

What is a variable?

Variables can generally be broken down into the following figure:

The focus of this section is to let everyone understand the "stack" of the memory model. For the time being, the "static variables" are not considered, and the following conventions are agreed:

"Global variables" simply default to "common global variables";

"Local variables" simply default to "ordinary local variables".

How to determine global variables and local variables?

To put it simply and intuitively, global variables are variables defined outside the function, and local variables are variables defined inside the function. The following example can clearly illustrate the judgment method of global variables and local variables:

unsigned char a; //在函数外面定义的, 所以是全局变量。
void main() //主函数
{
  unsigned char b; //在函数内部定义的, 所以是局部变量。
  b=a;
  while(1)
  { 
  
  }
}

Memory model of global variables and local variables

Microcontroller including memory ROMand a RAMtwo-part, ROMstorage is the microcontroller program instructions and data constants can not be changed, and RAMis stored in the variable data may be changed;

In other words, global variables and local variables are stored in RAM, but, although they are stored in, there are RAMstill obvious differences in the memory model between global variables and local variables.

Thus, two different sub- RAMregions, the global variable occupied RAMarea referred to the global data area , occupied by the local variable RAMregion called a stack .

What are the essential differences between their memory models?

The global data area is like your own room. It is unique. The address of a room can only be lived by you (assuming you were a single dog), and it is permanent (sorry), so every global variable is There is a unique corresponding RAM address, which cannot be repeated.

A stack is like an inn. The people who live in it every night are different throughout the year. Everyone has a time limit, not a long time. The address of a room may live in different people every day, not the only one. .

The global variables in the global data area have permanent property rights, and the local variables in the stack area can only temporarily live in hotels and inns. The address is not unique and has a time limit.

The stack is shared by the local variables inside all functions in the program. When the function is called, each local variable inside the function will be assigned to a certain address on the stack . RAMAfter the function call is over, the local variable becomes invalid. .

Thus its corresponding stack of RAMspace was withdrawn, in order to take up a local variable of the next function is called.

For example, "hotel inn" is used to compare the "stack" where local variables are located.

void function(void); //子函数的声明

void function(void) //子函数的定义
{
  unsigned char a; //局部变量
  a=1;
} 

void main() //主函数
{
  function() ; //子函数的调用
}

We see from the microcontroller to perform down the main function, the first encounter function()to call a subroutine, so jump to function()define where the function begins execution, a local variable at this time began to be assigned in RAMthe "stack area" of an address , It is equivalent to being assigned to a certain room when you stay in a hotel.

SCM executing the subroutine function(), the local variables in a RAMof 栈区the recovered assigned address, the disappearance of a local variable, repossessed RAMaddress system may be reassigned to other local variables of the called function.

This is equivalent to leaving the hotel. From then on, you have nothing to do with the hotel room. The room you used to stay in the hotel will be reassigned to other guests by the hotel owner.

The scope of a global variable is permanently unrestricted by scope, and the scope of a local variable is the internal scope of the function in which it is located. The global variable 全局数据区is a permanent private house, and the local variable is a temporary residence.

Summarized as follows

  1. Every time a new global variable is defined, it means that a new RAMmemory is spent. And each defines a local variable, as long as the total number of local variables inside a function defined by the microcontroller does not exceed the region, this time without the overhead of a new local variable RAMmemory, because local variables are temporarily borrowed and returned after use , public The area can be reused and can serve the local variables in several different functions.

  2. Every time the MCU enters the execution function, the local variables will be initialized and changed, but the global variables will not be initialized. The global variables always save the last changed value before.

What are the common questions?

Who allocated the global data area and the stack area behind the scenes, and how?

It is automatically allocated by the C compiler. As for how to allocate, who allocates more and who allocates less, the C compiler will have a default proportional allocation, which we generally don't care about.

The stack area is temporarily borrowed. When a sub-function is called, its internal local variables will be "temporarily" allocated to an address in the "stack" area. Then the question arises, who is behind the scenes of the "stack area". Assigned work?

When the MCU has been powered on and started to run the program, the compiler has no effect. The work of "stack area" allocated to the local variables of the function is indeed done by the C compiler, but this is before the MCU is powered on.

The C compiler has planned the allocation of the local variables in all functions. Once a function is called, which local variable in the function should be allocated to which address in the "stack area", C compiler The device ends his life after he has explained all these "futures" in advance.

When the microcontroller is powered on and starts to work, although the C compiler is no longer there, the microcontroller starts to work and allocate the "stack area" strictly in accordance with the will of the C compiler. Therefore, the "temporary allocation" of the "stack area" is not really a "temporary allocation" in the strict sense.

The total number of local variables defined in the function does not exceed the amount of RAM in the "stack" area of ​​the microcontroller. What if it exceeds the amount of RAM in the "stack" area, will the consequences be serious?

The technical term for this situation is called explosive stack . The program will appear inexplicable abnormalities, and the consequences are particularly serious.

In order to avoid this situation, in general, when writing a program, the local variables of a large array cannot be defined inside the function, and the number of local variables cannot be defined too much. In particular, avoid the definition of large array local variables just mentioned. Happening.

The definition of a large array should be defined as a global variable, or defined as a static local variable .

Some C compilers will kindly remind you that they will not be able to compile when they encounter a "burst stack" situation, but some C compilers may not remind you, so when you write functions for projects in the future, Be in awe of the explosive stack .

Priority of global variables and local variables

As mentioned earlier, the scope of global variables is permanent and unrestricted, while the scope of local variables is the internal scope of the function in which it resides.

So the question is, if the names of local variables and global variables have the same name, is the variable executed inside the function a local variable or a global variable?

This issue involves priority.

Note that when facing local variables and global variables with the same name, the variables executed inside the function are local variables, that is, local variables have higher priority than global variables inside the function.

Let's give some examples

Please see the first example below

unsigned char a=5; //此处第 1 个 a 是全局变量

void main() //主函数
{
  unsigned char a=2; //此处第2个a是局部变量,跟上面全局变量的第1个a重名了
  print(a); //把a发送到电脑端的串口助手软件上观察
  while(1)
  { 
  
  }
} 

The correct answer is 2. Local variables within a function have higher priority than global variables.

Although the two a here have the same name, their memory models are different. The a of the first global variable is allocated 全局数据区and has a unique address, while the a of the second local variable is allocated temporarily 栈区Yes, it is parasitic inside the main function.

Look at the second example below

void function(void); //函数声明
unsigned char a=5; //此处第1个 a 是全局变量

void function(void) //函数定义
{
  unsigned char a=3; //此处第 2 个 a 是局部变量。
} 

void main() //主函数
{
  unsigned char a=2; //此处第 3 个 a 也是局部变量。
  function(); //子函数被调用
  print(a); //把 a 发送到电脑端的串口助手软件上观察。
  while(1)
  {
  }
} 

The correct answer is 2. Because the function sub-function is called after the end of the call, print(a) is executed, which means that the local variable inside the function (the second local variable a) disappears when the print(a) statement is executed. , So the a of print(a) at this time is the a of the third local variable (a of the local variable defined in the main function).

Look at the third example below

void function(void); //函数声明
unsigned char a=5; //此处第1个a是全局变量

void function(void) //函数定义
{
  unsigned char a=3; //此处第2个a 是局部变量
} 

void main() //主函数
{
  function(); //子函数被调用
  print(a); //把a发送到电脑端的串口助手软件上观察
  while(1)
  {
  }
} 

The correct answer is 5. Because the function sub-function is called after the end of the call, print(a) is executed, which means that the local variable (the second local variable) inside the function function disappears when the function(a) statement is executed.

At the same time, because there is no local variable of a defined in the main function at this time, the a of function (a) must be the first global variable a (a of the global variable defined outside the main function) at this time.

At last

After reading this article, I believe that everyone has some basic understanding of the stack. In embedded programming, we should always pay attention to avoid stack explosion; if there are errors, please point out, we will see you in the next issue.

Recommended reading:

嵌入式编程专辑Linux 学习专辑C/C++编程专辑

关注微信公众号『技术让梦想更伟大』,后台回复“m”查看更多内容,回复“加群”加入技术交流群。
长按前往图中包含的公众号关注

Guess you like

Origin blog.csdn.net/u012846795/article/details/108396307