Operating system Stacks:
The assignment is released by the compiler on its own initiative and on its own initiative. The function that corresponds to the stack. Parameters store function values, completion values after function calls, and local variables in the function body. Segment memory space. Its operation and organization are very similar to the stacks in the data structure. The stack is designed to run the memory space that the thread leaves. The stack is created when the function is called. When the function is finished, the stack is recycled.
Heap in the operating system:
By the program Ape Manual memory application and release. Because the program ape manually applies and frees the memory blocks stored in the heap. There are very many blocks of memory in the heap, so the heap is organized in a similar way to a linked list. The heap in the operating system is completely different from the heap in the data structure. I think the popular understanding can be this: the heap in the data structure is the "structure heap". There are rigorous logic and operating methods. And the heap in the operating system. It's more like using a linked list to connect a bunch of messy stuff. A heap is a memory space reserved for dynamic allocation, whose life cycle is the entire application lifecycle.
When the application is finished, the heap starts to be recycled.
Each thread has a stack of its own, but each application usually has only one heap (and there is a case where an application uses multiple heaps). When the thread is created. Sets the size of the stack.
When the application starts, the heap size is set. The stack size is generally fixed, but the heap can be extended when needed, such as when a program ape requests a lot of other memory from the operating system.
Because the stack works like a stack in a data structure, the heap works like a linked list, so the stack is obviously much faster than the heap. Depending on how the stack is accessed, you want to free up memory or add memory. Just need to correspond to move the stack top pointer. The heap will first look for the appropriate memory space in the spare area of the memory and then occupy it. Then point to this space. Obviously heaps are much more complex than stacks.
The next step was to make a statement about the stack and the heap separately, or decide whether to compare stacks and heaps in the same way. The comparison is obvious.
1. When the stack is created, the stack size is fixed, as the stack takes up a space continuously. According to the characteristics of the heap, the size of the heap is dynamic, and its distribution and release are dynamic.
2. Too much data in the stack will cause the stack to explode. For example, Dfs writes and rubs.
And if the heap also explodes.
。 That means the memory has exploded, too.
3. Each function stack is separate, but the heap of an application is shared by all stacks.
Since sharing is mentioned, there is a "parallel access" problem. In fact, parallel access is controlled by the heap. Rather than being controlled by the stack.
4. The scope of the stack is limited to the inside of the function, and the stack frees the space itself at the end of the function. However, the variables created on the heap must be released manually. There is no scope problem with the variables in the heap. Because the heap is global.
5. The stack is stored in the function return value address, function parameters. Local variables within the function, and so on. The heap is a memory block (malloc, new, etc.) that is manually applied by the program ape.
6. The heap and stack are allocated on demand. The stack has a strict capacity limit. The capacity limit of the heap is "not strict". The heap does not have a fixed capacity limit, it is related to the current amount of remaining memory (in fact, it is not accurate, the operating system also has virtual memories or other concepts, so the heap works more abstractly).
7. The stack memory allocation can be achieved by moving the top pointer of the stack.
allocating memory on the heap is a way to find an area that satisfies the size of the current spare memory. Just like the way the list works.
8. Just do not exceed the stack capacity. The stack is free to release and request memory. does not cause memory failure and is safe. Unlike heaps, a large number of applications and releases of small chunks of memory can cause memory problems, and these small chunks of memory are scattered across memory. The memory request that caused a chunk may fail. Because although spare has enough memory. But not in succession. In this case, the small block of memory is called "heap fragmentation". It's just not a big problem. See the "Operating system" for more information.
9. After determining the stack address, the stack top pointer starts at the bottom of the stack. Gradually go to the low address. This means that the stack storage space is from high address to low address.
The heap, on the other hand, tends to look for available memory in the direction of the high address when the heap is in the application space.
The purely descriptive narrative looks dull, and we look at some code:
#include <iostream>using namespace std;void func () { int i = 5; int j = 3; int k = 7; int *p = &i; printf ("%d\n", *p); printf ("%d\n", * (p-1)); printf ("%d\n", * (P-2));} int main () { func (); GetChar (); return 0;}
The result of the above code is: 5 3 7
We can see two things from the results:
One is that the stack address is contiguous, and we can "offset" it to other variables by a pointer and a relative size.
The second is to be able to see that the stack address is from high to low distribution, stack bottom at high address. Grow in the direction of the low address.
So the program is p-1 instead of p+1.
void func () {int *p = null;//Upstream code is a priority. This pointer will later be used to request new memory. At this point, except that it takes 4 bytes of space as a variable (the pointer takes up 4 bytes), no matter what other space is applied. This pointer variable is a local variable of the function, so it is created on the stack. int num = 100; The same variable is created on the stack. int buffer[100];//the same, buffer occupies a stack of 400 bytes of space p = new int[100];//Note that the program ape manually applied for a space, this 400 bytes of memory is created on the heap. So the state of p at the moment is: P is a function local variable, it points to a global range of memory space. The}//function body ends. There is a serious problem with the above function, which is the memory leak of pointer p. The correct approach is to delete the memory at the end of the function. or return the address of this memory for continued use.
Now let's look at what happens when a function is called:
First, the operating system allocates a stack for this function. The first step is to press the address of the next instruction of the function to the stack, since it is necessary to return to the next statement correctly and continue running after the function is called. This way, when the function call is complete, the stack top pointer releases memory a little bit. The top pointer of the stack points to this address and can return to the correct location to continue running.
int main () {func ();p rintf ("%d\n"); return 0;}
For example, the preceding code, before calling Func, first put the next statement of Func, the address of the printf statement. exists on the stack.
This completes the function call and returns to the printf correctly and continues to run backwards.
Note that the address here is an instruction address, not a variable address or something. It has something like a program counter in the operating system (PC, ie Counter).
It then puts the real-right-to-left order into the stack (most C + + compilers are right-to-left) and then the various local variables in the function. It is important to note that the static variable in the function is not in the stack.
Global variables and static variables are already allocated memory in the static store at compile time.
Suppose this time the function calls another function, and the process is the same. The first is the return address, followed by the parameters and local variables.
This way, at the end of each layer call, when the top pointer of the stack drops (freeing memory), it is returned correctly to the previously called location and continues to run down.
Out of the stack. Or the process of freeing up memory. According to the characteristics of the stack, is the opposite, so do not repeat it.
A C or C + + program in which the memory address in the eye is divided into five regions:
Stack, heap area (heap), Global static zone (static), literal constant area, and program instruction area.
The stack area and the heap area have been described earlier. Global static zones are used to hold global variables and statically static static variables. The global static zone is divided into two pieces: a block for initializing global variables and static variables, one for uninitialized global variables and static variables. The global static zone, like the Heap, is released by the operating system after the program finishes. Literal constant areas are used to hold constant strings. Released by the operating system after the program finishes.
The program command area is best understood to be the binary instruction that holds the program code.
int cnt;//is stored in the uninitialized zone of the global static zone int num = 0;//the initialized zone of the global static zone int *p;//is stored in the uninitialized zone of the global static zone int main () {int I, J, k;//stored in the stack int *pbuffer = (int *) malloc (sizeof (int) * 10);//Pointer pbuffer in the stack, there is a heap of char *s = "Hactrox";//pointer s is stored in the stack, the string is stored in the literal constant area of char str[] = "Hactrox" ;//str and string stored in stack static int a = 0;//A is stored in the initialized zone of the global static Zone}
Char *s = "Hactrox"; "Hactrox" is in the literal constant area. S points to the "Hactrox" in this area, so this can be understood as. This string is created first in the literal constant area, and then s points to the two steps of the string.
s itself is stored in the stack as a local variable.
The following code is wrong, the pointer is not pointing to the direct assignment?
int *p = 5;
The following code is correct, first create this int type variable, and then p points to the variable. The new int variable is in the heap.
int *p = new int (5);
Let's take a look at a very common question: is there a problem with the following code? Where is the problem?
#include <iostream>using namespace std;char* F1 () { char *s = "Hactrox"; return s;} char* F2 () { char s[] = "Hactrox"; return s;} int main () { printf ("%s\n", F1 ()); printf ("%s\n", F2 ()); GetChar (); return 0;}
The problem is that the second function, F2, does not return the string correctly. In the function F1. The "Hactrox" string is created in the literal constant area. It then returns the address of the constant string, because the literal constant area of the string is global, although the pointer s is a local variable, but s before the extinction of the target address has been sent out. So s dying or not is the point. The point is that the area that the returned address points to is still there, so it will be displayed correctly. In the function F2. Both "Hactrox" and s are local variables. They are saved in the stack.
Although S returns an address in the same way. But the memory that this address points to has been released. The address is valid, but the destination is invalid. So the output is just garbled.
About the literal constant area other things to say (seems to be far from the topic of this blog?) )
#include <iostream>using namespace std;void func () {char *str1 = "123";p rintf ("%x\n", str1); char *str2 = "123";// Word constant area. The compiler may point str2 directly to the memory that str1 points to. Instead of opening up a new space to hold the second same string. You can verify printf ("%x\n", str2) by printing the str2 pointer, char *s1 = "Hactrox";p rintf ("%x\n", S1), char *s2 = "Hactrox";p rintf ("%x\n", S2);} int main () {func (); GetChar (); return 0;}
Char s[] = "Hactrox";
Char *s = "Hactrox Again";
The second piece of code, the literal constant area variable, is determined at compile time.
And the first piece of code. is assigned at the time of execution.
This looks like the second piece of code is more efficient. In fact otherwise,
When the two variables are used at execution time, for the first paragraph of code. Reads the string directly, and for the second segment of the code, first reads the string pointer. Then the string is read according to the pointer, obviously the efficiency is decreased.
In fact, I think the focus on stacks and heaps is actually focused on the scope, life cycle, and effectiveness.
The pointer is released. Does not mean that the memory pointed to by the pointer is freed. The same. The memory that the pointer is pointing to is freed, does not mean that the pointer is being released synchronously or that it is actively pointing to null, and the pointer still points to the invalid address. This address cannot be used. No one can guarantee a longer valid address and what happens next.
Copyright notice: This article blog original articles, blogs, without consent, may not be reproduced.
[Programming language] A comprehensive summary of stacks and stacks