Advanced C language 9: memory

1. Structure byte alignment

1.1 try

#include <stdio.h>
struct S1{
    char c1;
    char c2;
    int n;
};
struct S2{
    char c1;
    int n;
    char c2;
};
struct S3{
    int n;
    char c1;
    char c2;
};
int main(){
printf("sizeof(struct S1) = %ld\n",sizeof(struct S1));
printf("sizeof(struct S2) = %ld\n",sizeof(struct S2));
printf("sizeof(struct S3) = %ld\n",sizeof(struct S3));
}

Output result:

sizeof(struct S1) = 8
sizeof(struct S2) = 12
sizeof(struct S3) = 8

In C language, the memory occupied by structures is continuous, but the addresses between members are not necessarily continuous. So there is "byte alignment".

1.2 default principle of byte alignment

The size of the structure variable must be an integer multiple of the size of its largest data type. If the size of a data type is not enough, fill in bytes.
The address of a structure variable must be the same as that of its first member.

1.3 practice

#include <stdio.h>
 
struct Box{
    int height;
    char a[10];
    double width;
    char type;
};

int main(void) {
    struct Box box;
    printf("box = %p\n", &box);
    printf("box.height = %p\n", &box.height);
    printf("box.a = %p\n", box.a);
    printf("box.width = %p\n", &box.width);
    printf("box.type = %p\n", &box.type);
    printf("box = %d\n", sizeof(box));
    return 0;
}

Output result:

box = 0x7ffee0738c10
box.height = 0x7ffee0738c10
box.a = 0x7ffee0738c14
box.width = 0x7ffee0738c20
box.type = 0x7ffee0738c28
box = 32

2. Four memory areas

2.1 testing

#include <stdio.h>
#include <stdlib.h>

void f1(){
  int f1local1;
  int f1local2;
  static int f1static1;
  static int f1static2;
  int* f1dynamic1 = malloc(sizeof(int));
  int* f1dynamic2 = malloc(sizeof(int));
  printf("--------------f1()----------------\n");
  printf("&f1local1   = %p\n",&f1local1);
  printf("&f1local2   = %p\n",&f1local2);
  printf("&f1static1  = %p\n",&f1static1);
  printf("&f1static2  = %p\n",&f1static2);
  printf("f1dynamic1  = %p\n",f1dynamic1);
  printf("f1dynamic2  = %p\n",f1dynamic2);
  printf("\"f1string1\" = %p\n","f1string1");
  printf("\"f1string2\" = %p\n","f1string2");
  printf("--------------f1()----------------\n");
  free(f1dynamic1);
  free(f1dynamic2);
}
void f2(){
  int f2local1;
  int f2local2;
  static int f2static1;
  static int f2static2;
  int* f2dynamic1 = malloc(sizeof(int));
  int* f2dynamic2 = malloc(sizeof(int));
  printf("--------------f2()----------------\n");
  printf("&f2local1   = %p\n",&f2local1);
  printf("&f2local2   = %p\n",&f2local2);
  printf("&f2static1  = %p\n",&f2static1);
  printf("&f2static2  = %p\n",&f2static2);
  printf("f2dynamic1  = %p\n",f2dynamic1);
  printf("f2dynamic2  = %p\n",f2dynamic2);
  printf("\"f2string1\" = %p\n","f2string1");
  printf("\"f2string2\" = %p\n","f2string2");
  printf("--------------f2()----------------\n");
  free(f2dynamic1);
  free(f2dynamic2);
}

int static1;
int static2;
int main(){
  int local1;
  int local2;
  int* dynamic1 = malloc(sizeof(int));
  int* dynamic2 = malloc(sizeof(int));
  printf("&local1   = %p\n",&local1);
  printf("&local2   = %p\n",&local2);
  printf("&static1  = %p\n",&static1);
  printf("&static2  = %p\n",&static2);
  printf("dynamic1  = %p\n",dynamic1);
  printf("dynamic2  = %p\n",dynamic2);
  printf("\"string1\" = %p\n","string1");
  printf("\"string2\" = %p\n","string2");
  printf("&f1 = %p\n",&f1);
  printf("&f2 = %p\n",&f2);
  f1();
  f2();
}

Execution result:

&local1   = 0x7fff5345832c
&local2   = 0x7fff53458328
&static1  = 0x601050
&static2  = 0x601054
dynamic1  = 0x13dc2a0
dynamic2  = 0x13dc2c0
"string1" = 0x400bf7
"string2" = 0x400c0f
&f1 = 0x400666
&f2 = 0x400761
--------------f1()----------------
&f1local1   = 0x7fff534582fc
&f1local2   = 0x7fff534582f8
&f1static1  = 0x601040
&f1static2  = 0x601044
f1dynamic1  = 0x13dc6f0
f1dynamic2  = 0x13dc710
"f1string1" = 0x400a97
"f1string2" = 0x400ab3
--------------f1()----------------
--------------f2()----------------
&f2local1   = 0x7fff534582fc
&f2local2   = 0x7fff534582f8
&f2static1  = 0x601048
&f2static2  = 0x60104c
f2dynamic1  = 0x13dc710
f2dynamic2  = 0x13dc6f0
"f2string1" = 0x400b5f
"f2string2" = 0x400b7b
--------------f2()----------------

analysis:
(1) Local variables, static variables, dynamically allocated memory, string constants and functions are put together, even in different functions.
(2) The storage address size of variables has the following characteristics:
String constants and codes < static variables < dynamically allocated memory < local variables
(3) Static variables, dynamically allocated memory, string constants and adjacent variable addresses of functions are incremented. The addresses of local variables and adjacent variables are decremented.
(4) String constants are associated with functions.
The above description shows that the code is stored in different areas by type in memory.

2.2 stack

It is automatically allocated and released by the compiler. It mainly stores the values of function parameters and local variables.

2.3 heap

The programmer shall apply for allocation and release by himself. malloc(), calloc(), realloc() functions are required to apply for it, and free() function is used to release it. If it is not released, pointer dangling / wild pointer may appear.
The function cannot return a pointer to the stack area, but it can return a pointer to the heap area.

2.4 data area

Variables are marked with static keyword, which saves static variables.
1. Initialized global variables and initialized static variables are in one area;
2. Uninitialized global variables and uninitialized static variables are in a block area, which is called BSS(Block Started by Symbol);
3. The life cycle of static variables is the whole source program, and can only be initialized once. Subsequent initialization will be ignored.
(if not initialized, numerical data will be initialized to 0 by default, and character data will be initialized to NULL by default).
The array of the whole data area is uniformly destroyed by the system after the program is completed.

2.5 code area

Used to store compiled executable code, binary code and machine code.

3. The difference between heap and stack

No.Comparative aspectStackheap
1management styleIt is automatically managed by the system and takes the execution function as the unitManually controlled by the programmer
2Space sizeSpace size is determined at compile time (parameter + local variable)It is global and has no size limit.
3Distribution modeFunction execution, automatic allocation by the system; When the function ends, the system will automatically recycle it immediately.Use new/malloc() to allocate the release manually; Manually release using delete/free()
4advantageEasy to use, do not need to care about memory application release.Can be used across functions.
5shortcomingCan only be used inside functions.Easy to cause memory leakage.

4. Display target file section size: size command

Meaning of each section:

No.sectionnamemeaning
1textCode segment / text segmentThe area of memory where program execution code is stored. The size of this area is determined before running and is usually read-only. Some variables, such as read-only constants, may contain constants.
2dataData segmentAn area of memory that holds initialized global variables in a program. The data segment belongs to static memory allocation.
3bssBSS segmentAn area of memory that holds uninitialized global variables in a program. BSS is the abbreviation of English Block Started by Symbol. The BSS segment is a static memory allocation.

dec and hex are the sum of the first three regions, dec is decimal and Hex is hexadecimal.

Sections not shown:

No.sectionmeaning
1stackStore the local variables temporarily created by the program, that is, the variables defined in the function bracket {} (excluding the variables declared by static). When the function is called, the parameters will also be pushed into the process stack that initiated the call, and the return value of the function will also be stored back on the stack after the call.
2heapThe memory segment dynamically allocated by the storage program is not fixed in size and can be dynamically expanded or reduced. When malloc() and other functions are called to allocate memory, the heap is expanded; When functions such as free() are called to free up memory, the heap is reduced.

Keywords: C Back-end

Added by kippy on Thu, 10 Feb 2022 19:38:24 +0200