First, let's take a look at some basic knowledge to see how CLR works:
When CLR starts to load a Microsoft Windows Process, there may be multiple threads in the process. When a thread is created, it will be allocated to a 1 m stack, this stack space is used to pass real parameters to the method and store local variables defined inside the method, showing the stack memory of a thread (right side ). The stack is built from the high memory address to the low memory address. In the figure, this purebred executes someCodeIt has some data on the stack (displayed as the shadow area at the top of the stack). Now it is assumed that the Code executed by the thread needs to call the M1 method.
The most basic method should contain the "prologue" code, which is responsible for initializing the method before it starts to do its work, it should also contain an end-to-end (epilogue) code, which is responsible for cleaning the method after it is completed, so that it can be returned to the caller. When M1 starts execution, its "Opening Remarks" code allocates memory for the local variable name from the thread stack, such:
Then, M1 calls m2 and passes the local variable name as an instance. This causes the address in the name local variable to be pushed into the stack, for example:
When m2 starts execution, its "Opening Remarks" code allocates memory for the local variables length and tally from the thread stack, as shown in:
Then, execute the code inside the M2 method. In the end, M2 will arrive at its return statement, which will cause the CPU instruction pointer to be set to the return address in the stack, and the M2 stack frame will be unwind ), it looks like the second figure above. After that, M1 will continue to execute the code after m2 call, And the stack frame of M1 will accurately reflect the status required by M1.
In the end, M1 will return to its caller. This is also achieved by designing the cup instruction pointer as the return address, and the M1 stack frame will be rolled and opened, it looks like the first figure above. After that, the method that calls M1 will continue to execute the code after the M1 call. The stack frame of that method will accurately reflect the desired state.