当前位置:网站首页>Dynamic memory management

Dynamic memory management

2022-07-04 20:17:00 Hundred words lingdu

One 、 Why is there dynamic memory allocation

This is the memory development we master :

int arr[10]={
    0};// Open up on the stack 40 Byte space 
int num=0;// Open up on the stack 4 Byte space 

But there are two characteristics of the way to open up space :

1.  The size of the space opening is fixed .
2.  Arrays are declared , You must specify the length of the array , The memory it needs is allocated at compile time .
 But the need for space , It's not just that . Sometimes the amount of space we need is known when the program is running ,
 The way to open up space when compiling arrays is not enough .
 At this time, you need to dynamically open up memory .

Two 、 Introduction to dynamic memory functions

Add : What is the wild pointer ?

“ Wild pointer ” It means that the value in the pointer variable is an illegal memory address , but “ Wild pointer ” It's not a null pointer (NULL),“ Wild pointer ” The memory pointed to is not available ,“ Wild pointer ” It often leads to ” Memory out of bounds 、 Segment error “ Other questions

2.1 malloc( Will not initialize )

#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
    
    // Open up ten integer 
    int* arr = (int*)malloc(sizeof(int) * 10);
    if (NULL == arr)
    {
    
        printf("%s\n", strerror(errno));
        return 0;
    }
    // Use 
    int i = 0;
    for (i = 0; i < 10; i++)
    {
    
        *(arr + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
    
        printf("%d ", arr[i]);
    }
    // Release 
    free(arr);//free Can only release malloc,realloc,calloc Open up space 
    arr = NULL;// When released ,arr Became a wild pointer , So we need to take arr Into a NULL
    return 0;
}

2.2 calloc( Will be initialized to 0)

#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
    
    // Open up ten integer 
    int* arr = (int*)calloc(10, sizeof(int));
    if (NULL == arr)
    {
    
        printf("%s\n", strerror(errno));
        return 0;
    }
    // Use 
    int i = 0;
    for (i = 0; i < 10; i++)
    {
    
        printf("%d ", arr[i]);// Print 10 individual 0
    }
    // Release 
    free(arr);//free Can only release malloc,realloc,calloc Open up or adjust space 
    arr = NULL;// When released ,arr Became a wild pointer , So we need to take arr Into a NULL
    return 0;
}

2.3 realloc( Will not initialize )

2.3.1 characteristic

1、 Can open up space // When realloc The first parameter of is NULL when ,realloc Open up space 
//int*arr=(int*)realloc(NULL,40); 
2、 Space can be adjusted ( Two cases )// When realloc The first parameter of is not NULL when ,realloc Adjust the space 
//int*ptr=(int*)realloc(p,80);

give an example

2.3.2 Open up space

//1 Open up space 
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
    
    // Open up ten integer 
    int* arr = (int*)realloc(NULL, sizeof(int) * 10);
    if (NULL == arr)
    {
    
        printf("%s\n", strerror(errno));
        return 0;
    }

    // Use 
    int i = 0;
    for (i = 0; i < 10; i++)
    {
    
        *(arr + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
    
        printf("%d ", arr[i]);
    }
    // Release 
    free(arr);//free Can only release malloc,realloc,calloc Open up or adjust space 
    arr = NULL;// When released ,arr Became a wild pointer , So we need to take arr Into a NULL
    return 0;
}

2.3.3 Adjust the space

//2 Adjust the space 
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
    
    // Open up ten integer 
    int* arr = (int*)calloc(10, sizeof(int));
    if (NULL == arr)
    {
    
        printf("%s\n", strerror(errno));
        return 0;
    }

    // Use 
    int i = 0;
    for (i = 0; i < 10; i++)
    {
    
        printf("%d ", *(arr+i));
    }

    // Need to increase capacity 80
    int* ptr = (int*)realloc(arr, sizeof(int) * 20);

    // If the adjustment fails , prevent NULL Assign to arr
    if (NULL != ptr)
    {
    
        arr = ptr;
        ptr = NULL;
    }

    // Continue to use 
    for (i = 10; i < 20; i++)
    {
    
        *(arr + i) = i;
    }
    for (i = 10; i < 20; i++)
    {
    
        printf("%d ", *(arr+i));
    }
    // Release 
    free(arr);//free Can only release malloc,realloc,calloc Open up or adjust space 
    arr = NULL;// When released ,arr Became a wild pointer , So we need to take arr Into a NULL
    return 0;
}

realloc There are two situations when adjusting space

1、

Case one , When we use realloc When adjusting space , If there is enough space behind the original dynamic space , Then it will continue to expand space . Return the address pointing to the starting position of the original opening space .

2、

The second case , When we use realloc When adjusting space , If the space originally opened dynamically is not expanded enough in the subsequent space , Then you will find enough space , And copy the contents of the original dynamic space , Return the address pointing to the starting position of the post opening space .

3、 ... and 、 Common dynamic memory errors

3.1 Yes NULL Dereference operation of pointer

#include<limits.h>//INT_MAX Required header file 
#include<stdlib.h>
int main()
{
    
    int*p=(int*)malloc(INT_MAX);// Open up failure return NULL
    if(p==NULL)
        return 0;
    int i=0;
    for(i=0;i<10;i++)
    {
    
        *(p+i)=i;
    }
    return 0;
}

3.2 Space for dynamic memory

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
int main()
{
    
    char*p=(char*)malloc(10*sizeof(char));
    if(p==NULL)
    {
    
        printf("%s\n",strerror(errno));
    }
    // Use 
    int i=0;
    for(i=0;i<=10;i++)
    {
    
        *(p+i)=i;
    }
    free(p);
    p=NULL;
    return 0;
}

3.3 Free space for non dynamic memory

int main()
{
    
    int a=10;
    int*p=&a;
    free(p);// error ,free Can only release malloc,realloc,calloc Open up or adjust space 
    p=NULL;
    
    return 0;
}

notes : The stack in the data structure cannot be equated with the stack area in the memory

3.4 Use free Release a piece of dynamic memory

int main()
{
    
    int*p=(int*)malloc(sizeof(int)*10);
    if(p==NULL)
    {
    
        printf("%s\n",strerror(errno));
        return 0;
    }
    // Use 
    int i=0;
    for(i=0;i<5;i++)
    {
    
        *P=i+1;
        p++;
    }
    // Release 
    free(p);//p Does not point to the starting position of dynamic memory 
    p=NULL;
    return 0;
}

3.5 Multiple releases of the same block of memory

int main()
{
    
    int*p=(int*)malloc(sizeof(int)*10);
    if(p==NULL)
    {
    
        printf("%s\n",strerror(errno));
        return 0;
    }
    // Use 
    int i=0;
    for(i=0;i<5;i++)
    {
    
        *(P+i)=i+1;
    }
    // Release 
    free(p);

    free(p);// error , Release many times ; If after the first release , take p Set to null pointer , Can be released again 
    return 0;
}

3.6 Dynamic memory forget to release ( Memory leak )

void test()// Forgetting to release the dynamically opened space that is no longer used will cause memory leakage 
{
    
    int*p=(int*)malloc(100);
    if(NULL!=p)
    {
    
        *p=20;
    }
}

int main()
{
    
    test();
    while(1);
}

Four 、 Several classic written test questions

function Test What is the result of the function ?

Example 1

void GetMemory(char *p)
{
    
    p = (char *)malloc(100);
}
void Test(void)
{
    
    char *str = NULL;
    GetMemory(str);
    strcpy(str, "hello world");
    printf(str);
}
int main()
{
    
    Test();
    return 0;
}

answer : Program error

1、strcpy The first argument to the function is a null pointer ( because GetMemory When a function passes parameters, it passes the value of the pointer , therefore ,str The content of will not change )

2、 After dynamically opening up memory , There is no release , Memory leaks can result

Example 2( Return stack space address problem )

char *GetMemory(void)
{
    
    char p[] = "hello world";
    return p;
}
void Test(void)
{
    
    char *str = NULL;
    str = GetMemory();
    printf(str);
}
int main()
{
    
    Test();
    return 0;
}

answer : Program error

1、 stay GetMemory When the function is finished ,p Variables will be destroyed , Assign the address of destruction to str, Re print , Will form illegal access

Example 3

void GetMemory(char **p, int num)
{
    
    *p = (char *)malloc(num);
}
void Test(void)
{
    
    char *str = NULL;
    GetMemory(&str, 100);
    strcpy(str, "hello");
    printf(str);
}
int main()
{
    
    Test();
    return 0;
}

answer : Print hello
1、 The space opened up by dynamic memory is not released , Memory leaks can result

Example 4

void Test(void)
{
    
    char *str = (char *) malloc(100);
    strcpy(str, "hello");
    free(str);
    if(str != NULL)
    {
    
        strcpy(str, "world");
        printf(str);
    }
}
int main()
{
    
    Test();
    return 0;
}

answer :

1、 stay free(str) after , Didn't put str Set as NULL

1、 stay str After the space pointed to is released , You can't use , It will cause illegal access to memory .

5、 ... and 、C/C++ Program memory development

C/C++ Several areas of program memory allocation :

1、 The stack area (stack): When executing a function , The memory units of local variables in the function can be created on the stack , At the end of the function, these storage units are automatically released . Stack memory allocation operations are built into the processor's instruction set , It's very efficient , But the allocated memory capacity is limited . The stack area mainly stores the local variables allocated by running functions 、 Function parameter 、 Return the data 、 Return address, etc .

2、 Heap area (heap): Release is usually assigned by the programmer , If programmers don't release , At the end of the program, the OS Recycling . The distribution is similar to a linked list .

3、 Data segment ( Static zone ): Store global variables 、 Static data . Released by the system at the end of the program .

4、 Code segment : Store function body ( Class member functions and global functions ) The binary code of .

6、 ... and 、 Flexible array

C99 in , The last element in the structure is allowed to be an array of unknown size , This is called 『 Flexible array 』 member .

for example :

//1
struct s1
{
    
    int n;
    int arr[0];// The size is unspecified 
};
//2  For some compilers, the first writing method will report an error and cannot be compiled. You can use the second writing method 
struct s2
{
    
    int n;
    int arr[];
};

6.1 The characteristics of flexible arrays

• A flexible array member in a structure must be preceded by at least one other member .
sizeof The size of the structure returned does not include the memory of the flexible array .
• Structures that contain flexible array members use malloc () Function to dynamically allocate memory , And the allocated memory should be larger than the size of the structure , To fit the expected size of the flexible array

typedef struct st_type
{
    
    int i;
    int a[0];// Flexible array members 
}type_a;
printf("%d\n", sizeof(type_a));// The output is 4

6.2 The use of flexible arrays

// Code 1
int i = 0;
type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
// Use 
p->i = 100;
for(i=0; i<100; i++)
{
    
    p->a[i] = i;
}
free(p);

So flexible array members a, It's equivalent to getting 100 A continuous space of integer elements .

6.3 The advantages of flexible arrays

Aforementioned type_a The structure can also be designed as :

// Code 2
typedef struct st_type
{
    
    int i;
    int *p_a;
}type_a;
type_a *p = (type_a *)malloc(sizeof(type_a));
p->i = 100;
p->p_a = (int *)malloc(p->i*sizeof(int));
// Use 
for(i=0; i<100; i++)
{
    
    p->p_a[i] = i;
}
// Release space 
free(p->p_a);
p->p_a = NULL;
free(p);
p = NULL;

The code above 1 And code 2 The effect is the same , What's the difference? ? Which is better ?

Code 1:

Code 1 Opening up space in memory , Pictured above

In the code 1 The situation of ,malloc once type_a Type structure is enough .

Code 2:

Code 2 Opening up space in memory , Pictured above

Code 2 If you want to achieve the effect of code one , It needs to be done first malloctype_a Type of structure , Again malloc A continuous space , This needs to be done twice malloc, It also needs to be done twice free, At the same time, it will also produce memory fragments .

summary :

Above Code 1 and Code 2 It can do the same thing , however Method 1 There are two benefits to the implementation of :

The first advantage is : Convenient memory release
If our code is in a function for others , You do a secondary memory allocation in it , And return the whole structure to the user . The user calls free You can release the structure , But the user doesn't know that the members in the structure also need free, So you can't expect users to find out . therefore , If we allocate the memory of the structure and its members at one time , And return a structure pointer to the user , The user does it once free You can also free up all the memory .
The second advantage is : This is good for access speed .
Continuous memory is good for improving access speed , It also helps reduce memory fragmentation .

原网站

版权声明
本文为[Hundred words lingdu]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202141133396055.html