c language heap, stack, data segment, code segment and bss segment

Posted by johnkperks on Wed, 02 Mar 2022 12:34:30 +0100

Program memory allocation

The memory occupied by a program compiled by c/C + + is divided into the following parts
1. Stack - automatically allocated and released by the compiler to store the parameter values of functions and the values of local variables. Its operation mode is similar to the stack in the data structure.
2. Heap - generally allocated and released by the programmer. If the programmer does not release it, it may be recycled by the OS at the end of the program. Note that it is different from the heap in the data structure, and the allocation method is similar to the linked list.
3. Global area (static) - global variables and static variables are stored together. Initialized global variables and static variables are in one area, and uninitialized global variables and uninitialized static variables are in another adjacent area- System release after program
4. Text constant area - constant string is placed here. Released by the system at the end of the program
5. Program code area - the binary code that holds the function body.

Procedure description:

//main.cpp
int a = 0; //Global initialization area
int a = 0; //Global initialization area
char *p1; //Global uninitialized area
main() {
    int b; //Stack
    char s[] = "abc"; //Stack
    char *p2; //Stack
    char *p3 = "123456"; //123456 \ 0 is in the constant area and p3 is on the stack.
    static int c = 0; //Global (static) initialization area
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20);
    //The area allocated with 10 and 20 bytes is in the heap area.
    strcpy(p1, "123456"); //123456 \ 0 is placed in the constant area, and the compiler may optimize it in the same place as the "123456" pointed to by p3.
}

Stack features:

1. Runtime automatic allocation and automatic recycling: the stack is automatically managed, and programmers do not need manual intervention. Convenient and simple.
2. Reusability: there is actually that space in the program in the stack, and the program uses this space repeatedly.
3. Legacy: due to repeated use of stack memory, the program will not clean up after each use, so it is still the value left in the last stack when using the stack.
4. Temporary: (the function cannot return the pointer of the stack variable because this space is temporary).
5. Overflow: because the operating system gives the size of the stack in advance, if the stack is allocated endlessly in the function, the memory can always be used up.

Microsoft YaHei example
color=#00ffff

heap

Role of reactor

For the heap, our programmers are free to allocate the memory size, but when you allocate the memory size to a pointer variable, remember to release it before the return 0 statement of the main program, otherwise there will be a bad impact - memory leakage.

How to allocate and free memory size?

In c language, we often use malloc to allocate the memory size (but you should not allocate more memory than the system memory size, otherwise you will report an error. The general system memory size is 4G. As for why, readers can baidu this reason, I won't talk about it here), and use the free function to release the previously allocated memory size.
void *malloc(size_t size);
void free(void *ptr);
explain

 (1)void *Is a pointer type, malloc Returns a void *Pointer to type, essentially malloc The first address of the memory space allocated to me by the heap manager is returned( malloc The returned value is actually a number, which represents a memory address). Why use void *As type? The main reason is malloc When we allocate memory, we only allocate memory space. What type of elements will this space be used to store in the future malloc We don't care. It's up to our program to decide.
  
 (2)What is? void Type. It was translated into empty type in the early stage. This translation is very bad and misleading. void Type does not mean no type, but universal type. void This means that the type of this data is currently uncertain, and its specific type can be specified when necessary. void *Type is a pointer type. The pointer itself occupies 4 bytes, but the type pointed to by the pointer is uncertain. In other words, the pointer can be forcibly converted to any other pointer of a certain type when needed, that is, the pointer can point to any type of element.

 (3)malloc Return value of: the pointer of the memory space is returned after the successful application of space, and when the application fails NULL. therefore malloc Before using the obtained memory pointer, be sure to check whether it is NULL. 

 (4)malloc When the requested memory is used up, you should free Release. free(p);I will tell the heap manager that I have run out of memory and you can recycle it.

(5)Re call free The pointer to this memory before returning it p You must not lose it p Additional assignment). because p Once you lose this paragraph malloc The memory will be lost forever (memory leak), and the operating system will not recycle this memory until the end of the current program.

Some details of malloc usage:

malloc(0) (this is meaningless, but I'd like to share it). Malloc's application for 0 bytes of memory itself is a nonsense. Generally, this need will not be met. If malloc(0) returns NULL or a valid pointer? The answer is: a 20Byte memory is actually allocated and the address of this memory is returned. This answer is not certain, because the C language does not specify the performance of malloc(0), which is defined by the implementer of each malloc function library (this test does have different results in different environments).

Code segment, data segment, bss segment:

When compiling the program, the compiler divides all the elements in the program into some components, and each part forms a segment, so the segment is a component of the executable program.

1. What is a code snippet

Code segment is the executable part of the program. It is intuitively understood that the code segment is composed of function stack (that is, the part of the program in the function body).

2. What is a data segment

(it is also called data area, static data area and static area): the data segment is the data in the program, and the intuitive understanding is the global variable in the C language program. (Note: the global variable is the data of the program, and the local variable is not the data of the program (it is on the stack), but only the data of the function).

3. What is a bss segment

(it is also called ZI(zero initial): the bss segment is characterized by being initialized to 0. bss segment essentially belongs to data segment, and bss segment is the data segment initialized to 0.

Difference and relation between data segment (. Data) and bss segment:

There is no essential difference between them. They are used to store the global variables in C program. The difference lies in the existence of global variables that initialize the display to non - zero In the data section, the bss section exists for global variables that are explicitly initialized to 0 or not explicitly initialized (the default value of global variables that are not explicitly initialized is 0 according to the C language).

4. Some special points to pay attention to

a. Some special data will be put into the code segment

 1  #include <stdio.h>
 2  #include <stdlib.h>
 3
 4
 5 int main(void)
 6 {
 7     char *p ="linux";
 8     //You'd better write const char *p="linux";
 9    *(p+0)='f';//Originally, it should be finux 
10
11        return 0;
12  }

Result: segment error
explain
char *p = "linux" is used in C language; When defining a string, the string "linux" is actually assigned to the code segment, that is, the "linux" string is actually a constant string rather than a variable string.

b. Global variables and static local variables explicitly initialized to non-zero are placed in the data segment

Put it on There are two kinds of variables in the data section: the first is a global variable explicitly initialized to non-zero. The second is static local variables, that is, static modified local variables. Static variables are allocated on the stack (local variables are allocated on the stack).

c. Global variables that are not initialized or explicitly initialized to 0 are placed in the bss segment

5. Summary

 (1)The same point: the three methods of obtaining memory can provide available memory for the program, and can be used to define variables for the program.

 (2)Difference: stack memory correspondence C Ordinary local variables in (other variables can't use the stack, and the stack is automatic, which is provided by the compiler and the runtime environment, and the programmer can't control it manually); Heap memory is completely independent of our program existence and management. When the program needs memory, it can be applied manually malloc,It must be used as soon as possible free Release. Heap memory is to programs what a public library is to people,In borrowing and returning books, when we borrow books, we borrow them from the library. After reading the borrowed books, we should return them to the library; The data segment corresponds to the program C Global variables and static local variables in the program.
 
 (3)If I need a piece of memory to store data, where should I store this data? (or if I want to define a variable, should I define it as a local variable or a global variable or use malloc To achieve). Different storage methods have different characteristics, which are briefly summarized as follows:

It is used temporarily inside the function. If it is not used outside the function, local variables are defined. Heap memory and data segments have almost identical properties and can be completely replaced most of the time. But the life cycle is different. The life cycle of heap memory starts from malloc to free, while the global variable starts from the execution of the whole program and will not disappear until the end of the whole program, which is accompanied by the life of the program. Revelation: if your variable is only useful at one stage of the program, it will not be used up. It is suitable for heap memory; If this variable itself is associated with the program for a lifetime, it is suitable to use a global variable. (heap memory is like renting a house, and data segment is like buying a house. Heap memory is like borrowing books from the library, and data segment is like buying books in your own bookstore.) you will gradually find that buying is better than renting, and heap memory is more widely used than global variables. Here is an example demonstration

 1#include <stdio.h>
 2#include <string.h>
 3#include <stdlib.h>
 4
 5
 6int a = 5;
 7int b;//This is the bss segment
 8int c = 0;//This is the bss segment
 9int array[1000];
10
11 char str[] = "linux";        // The second method: define it as a global variable and put it in the data segment
12
13
14int main(void)
15{
16   char a[] = "linux";     // The first method: define it as a local variable and put it on the stack
17
18   char *p = (char *)malloc(10);   
19   if (NULL == p)
20   {
21    printf("malloc error.\n");
22    return -1;
23   }
24  memset(p, 0, 10);       // The third method: put it in the heap memory requested by malloc
25  strcpy(p, "linux");
26
27  printf("%s\n", a);
28  printf("%s\n", str);
29  printf("%s\n", p);
30  printf("%p\n", a);
31  printf("%p\n", str);
32  printf("%p\n", p);
33
34   free(p);
35return 0;
36}

Presentation results:

Topics: C Embedded system Single-Chip Microcomputer