当前位置:网站首页>Advanced C language (XII) - dynamic memory management
Advanced C language (XII) - dynamic memory management
2022-07-25 08:00:00 【Not yet】
Catalog
- Preface
- 1. Why dynamic memory allocation occurs
- 2. Dynamic memory functions
- 3. Common dynamic memory errors
- 4. C/C++ Program memory development
- 5. Flexible array (flexible array)
- Conclusion
Preface
C The most important knowledge point in language is The pointer And Dynamic memory management , This is a test C An important criterion for language learning .
1. Why dynamic memory allocation occurs
The first method we come into contact with to apply for space from the operating system is often to create a variable 、 Array form , This applies for a fixed memory size , Often can not meet the needs well . such as The application is too small to use , There is waste when the application is large . Dynamic memory solves this problem well , We can apply for a space first , When you are small, you are applying for a larger space , You can also apply for a smaller space when you are big .
int a = 10;// Open up four bytes of space on the stack space
char ch[20] = "Hello world!";// Open up in stack space 20 Bytes of space
The characteristics of applying for memory in common way :
- The size of the requested memory is fixed .
- When defining an array, you must specify the length of the array (C99 Variable length arrays were not previously supported ), The memory it needs is allocated at compile time .
Variable length array (C99 Standards support )
It refers to an array declared or defined with integer variables or expressions , The length of the array does not change at any time .
After the length of the variable length array is determined The length in the life cycle is fixed .
Variable length array Cannot initialize when defining .
Variable length array Must be defined within the scope of the block , Variable length arrays cannot be defined within the scope of the file .
Variable length arrays cannot be usedstaticorexternmodification .
Variable length array Cannot be a member of a structure or union , It can only exist in the form of independent arrays .
Variable length array Scope is the scope of the block , The lifecycle is also the scope of the block .
Example :
#include <stdio.h>
int main(){
int n = 0;
scanf("%d", &n);
int arr[n];
int i = 0;
for(i=0; i<n; i++){
arr[i] = i;
}
for(i=0; i<n; i++){
printf("%d ", arr[i]);
}
return 0;
}
2. Dynamic memory functions
The memory space of ordinary variables belongs to the stack area .
The dynamically opened memory space belongs to the heap area of memory .
2.1 malloc() and free()
malloc() Function declaration
void* malloc(size_t size);
The header file <stdlib.h>
function : Apply to memory for a continuous available space , And return the pointer to this space .
If It's a success , Returns the pointer to this space ;
If Failed to open up , Return null pointer (NULL), Should checkmallocTo prevent the return of null pointers ;
The argument to the function issize, Number of bytes to apply , Typesize_t, Unsigned integer .
The return value type is An untyped pointervoid*, When using the return value You need to cast a pointer to the type you want .sizeIf the value of is passed in0,** Whether the result is a null pointer or another value is uncertain ,**C Language standards are not defined , It depends on the specific compiler .
malloc() Space to apply Will not initialize automatically , It's a random value , Manual initialization is required .
free() Function declaration
void free(void* ptr);
The header file <stdlib.h>
function : Used to release dynamic development (
malloc()、calloc()、realloc()) Memory block .
If parametersptrThe pointed space is not opened dynamically , befree()Of Behavior is undefined .
If parametersptryes Null pointerNULL, befree()Do nothing .
Generally, the pointer is releasedptrAfter pointing to the dynamically opened memory block, you need to put the pointerptrSet to null pointer . OtherwiseptrIt becomes a wild pointer , Very dangerous .
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(){
int n = 0;
scanf("%d", &n);
// apply 4*n Bytes of space
int* p = (int*)malloc(sizeof(int) * n);
// Check p Whether it is a null pointer , If it is to output an error message and return
if(p == NULL){
printf("%s\n", strerror(errno));
return 1;
}
int i = 0;
for(i=0; i<n; i++){
*(p+i) = i;
}
for(i=0; i<n; i++){
printf("%d ", *(p+i));
}
// Release integer pointer p Point to the dynamic memory development ( apply ) Space
free(p);
// The pointer p The pointer is set to null (NULL)
p = NULL;
return 0;
}
2.2 calloc()
Function declaration
void* calloc(size_t num, size_t size);
The header file <stdlib.h>
function : by
numSize issizeThe element of allocates a space , And put everyone in this spacebitAll initialized to 0.
Ifsizeyes0, Then the return value is undefined ( Not necessarily a null pointer ), It depends on the specific compiler .
Andmalloc()Differences in allocation results It's just thatcalloc()Will allocate space for eachbitInitialize to 0.
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
int n = 10;
int* p1 = (int*)malloc(sizeof(int) * n);
if (p1 == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
int* p2 = (int*)calloc(n, sizeof(int));
if (p2 == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
int i = 0;
for (i = 0; i < n; i++) {
printf("%d ", *(p1 + i));
}
printf("\n");
for (i = 0; i < n; i++) {
printf("%d ", *(p2 + i));
}
return 0;
}
Running results :
2.3 realloc()
Function declaration
void* realloc(void* ptr, size_t size);
The header file <stdlib.h>
function : The pointer
ptrWhen not null pointer , Reallocate memory blocks .
There are two situations :
- The space to be reapplied is larger than the original space and there is enough space behind the original space or The space to be reapplied is smaller than the original space
realloc() function Apply for additional space directly behind the original space , The original spatial data does not change , The return value of the function is the starting address of the old space , Is a pointer ptr Value .
- The space to be reapplied is larger than the original space And There is not enough space behind the original space
realloc() Function in Apply for a large enough continuous space as a new space in the appropriate place of the stacking area , The return value of the function is the start of a new space Starting address , And ptr Value Different .
The value of the newly assigned part Uncertain , namely It's a random value .
ptrIs the memory address to be adjusted .sizeWhen adjusted, the new size .
The return value is the starting position or null pointer of the adjusted memory block .
realloc() Function adjusts the size of the original memory space , Will also The data in the original memory is moved to the new space .
When incoming**ptr**When it's a null pointer ,realloc Function is equivalent to malloc Function functions .


Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main() {
int n = 0;
scanf("%d", &n);
int* ptr = (int*)calloc(n, sizeof(int));
if (ptr == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
int i = 0;
for (i = 0; i < n; i++) {
printf("%d ", *(ptr + i));
}
printf("\n");
// Reallocate memory block size
scanf("%d", &n);
int* p = (int*)realloc(ptr, sizeof(int) * n);
if (p != NULL) {
ptr = p;
}
for (i = 0; i < n; i++) {
printf("%d ", *(p + i));
}
free(ptr);
ptr = NULL;
return 0;
}
Dynamic memory application space will have time overhead , Multiple dynamic applications for space will take time , It leads to the decrease of program efficiency , And generate more memory fragments . Use the memory pool to apply for enough memory space at one time , The program manages the memory pool itself , No more space applications to the operating system , The problem ahead has been solved very well .
3. Common dynamic memory errors
3.1 In the air (NULL) Dereference operation of pointer
After dynamically opening up memory, it can be used directly without checking its returned pointer , Memory development may fail , At this time, the null pointer is returned .
Examples of mistakes :
#include <stdio.h>
#include <stdlib.h>
int main(){
int* p = (int*)malloc(sizeof(int) * 10);
*p = 10;
free(p);
return 0;
}
3.2 Cross border access to dynamically opened space
A dynamic space The size is certain , Do not pay attention to the control of the boundary when accessing the dynamically opened space , It may lead to cross-border visits , Become Wild pointer , Cause program error .
Examples of mistakes :
#include <stdio.h>
#include <stdlib.h>
int main() {
int* p = (int*)malloc(INT_MAX);
// Check p Whether it is a null pointer
if (p == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
int i = 0;
for (i = 0; i <= 10; i++) {
//i be equal to 10 Cross border visits when
*(p + i) = i + 1;
}
// Release pointer p The space it points to
free(p);
p = NULL;
return 0;
}
3.3 Use free() Free non dynamic memory space
free()Only dynamically opened memory space can be released . The dynamically opened memory space belongs to the heap , Instead of dynamically opening up space in the stack area 、 Memory areas such as static areas .
Examples of mistakes :
#include <stdio.h>
#include <stdlib.h>
int main(){
int a= 10;
int* p = &a;
// Release local variables a Stack space , error
free(p);
p = NULL:
return 0;
}
3.4 Use free() Release a part of the dynamically opened memory space
In the use of
malloc()、calloc()、realloc()The function will return the starting address of this memory space after successfully applying for a memory space in the heap . We usually use some kind of pointerptrTo receive this address , This is normal operation .
But in the next use of this space , It may make the pointerptrPoint to other non starting addresses of this memory space , And the user didn't notice this and directly responded toptrA part of the dynamically opened memory space pointed to has been released , Make a mistake .
Examples of mistakes :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(){
int* p = (int*)malloc(sizeof(int) * 10);
// Check p Whether it is a null pointer
if(p == NULL){
printf("%s\n", strerror(errno));
}
int i = 0;
for(i=0; i<10; i++){
*p = i;
p++;
}
// Release pointer p The space it points to
free(p);
p = NULL;
return 0;
}
3.5 Multiple releases of the same dynamic memory
The pointer
ptrPoint to themalloc() or calloc() or realloc()The requested memory space passes through the pointer many times after it is used upptrFreeing this memory space will also cause program errors .
For the first timefree()Release pointerptrThe memory space pointed to is a normal operation that meets the requirements ; But for the first timefree()Didn't put it in timeptrSet asNULL, hereptrIt refers to the memory space that has been released , This memory space no longer belongs to this program .ptrThis is the wild pointer , AgainptrConductfree()Illegal access to memory , Make a mistake .
Examples of mistakes :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(){
int* p = (int*)malloc(sizeof(int) * 10);
if(p == NULL){
printf("%s\n", strerror(errno));
return 1;
}
// Multiple releases p The memory space pointed to
// The first is normal release
free(p);
// The second time p It's a wild pointer , Illegal access to memory , There has been an error here , The program to stop
free(p);
free(p);
return 0;
}
3.6 Dynamically opened memory space forgot to release ( Memory leak )
Memory leaks are often the culprit for slow programs , Although we will not intentionally take the initiative to write code that causes memory leaks , But memory leaks will still appear quietly when there are loopholes in our logic , Cause the program to have problems that appear with the increase of running time .
The dynamically opened memory space has not been released , Not used , Because I forgot to release or there was a logical problem, I didn't release , The result is that although this memory space is still there , But the program itself is not used ( The program has been used up ), Because this space system has been allocated to the program , So there is no way to use the system , It's equivalent to this memory being lost , Until the program stops, the operating system automatically reclaims this memory space , Memory space can be used again , Is equivalent to being found .
Examples of mistakes :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void test() {
int* p = (int*)malloc(sizeof(int) * 10);
if (p == NULL) {
printf("%s\n", strerror(errno));
return 0;
}
int i = 0;
for (i = 0; i < 10; i++) {
*(p + i) = i;
}
for (i = 0; i < 10 ; i++) {
printf("%d ", p[i]);
}
// There is no release p The dynamically opened memory space pointed to
}
int main() {
while (1) {
test();
}
return 0;
}
4. C/C++ Program memory development

C/C++ Area description of program memory allocation
The stack area
stack:
When executing a function , The storage unit 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 is mainly used to store the... Allocated by running the function local variable 、 Function parameter 、 Return the data 、 The return address etc. .
Stack area is from High address towards Low address Expand , It's one piece Contiguous areas of memory , follow First in, then out , Last in, first out Principles .
Heap area
heap:
Release is usually assigned by the programmer , If the programmer doesn't release , At the end of the program, the OS( operating system ) Recycling .
The distribution is similar to a linked list . It can be discontinuous .
The stacking area is made up of Low address towards High address Expand , Contrary to stack area , follow fifo 、 last in last out Principles .
The first address of the opened space is in the stack area .
Static zone
**static**:
Store global variables 、 Static data . After the program ends, the space is released by the system .
During the execution of the procedure ( Life cycle ) Always exist .
BystaticModified local variables Life cycle No longer the current code block , But during the whole process ; But the scope is still the current code block .
The constant area :
Store constants , During the execution of the whole program , And cannot be changed .
System management space .
Code section :
Store function body ( Class member functions and global functions ) The binary code of .
5. Flexible array (flexible array)
Flexible arrays are rarely used , But there are also ways to use .
C99 Said : The last element in a structure is allowed to be an array of unknown size , Such an array is called a flexible array member .
5.1 Declaration of flexible arrays
struct student{
char name[20];
int arr[0];
};
perhaps :
struct student{
char name[20];
int arr[];
};
- The structure of the Flexible array members must be preceded by at least one other member .
- In a structure Flexible array members can only have one .
sizeof()The size of this structure returned does not include the memory of the flexible array .- The structure containing flexible array members is used
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 .
Observe the size of the structure :
#include <stdio.h>
struct student {
char name[20];
int arr[];
};
int main(){
int ret = sizeof(struct student);
printf("%d\n", ret);
return 0;
}
Running results :
5.2 The use of flexible arrays
Example :
Structures with flexible array members use malloc() Allocate dynamic memory , The allocated size contains The size of the structure itself + The size of the flexible array .
Dynamic memory development diagram :
#include <stdio.h>
#include <stdlib.h>
struct S{
int i;
int arr[];
};
int main(){
// Structures with flexible array members use malloc() Allocate dynamic memory
// The allocated size includes the size of the structure itself + The size of the flexible array
struct S* p = (struct S*)malloc(sizeof(struct S) + sizeof(int) * 10);
// Check p Whether it is a null pointer
if(p == NULL){
printf("%s\n", strerror(errno));
return 1;
}
// Use flexible arrays
int i = 0;
for(i=0; i<10; i++){
p->arr[i] = i;
}
for(i=0; i<10; i++){
printf("%d ", p->arr[i]);
}
// Release p Points to the dynamically opened memory space and will p Set to null pointer
free(p);
p = NULL;
return 0;
}
Running results :
5.3 The advantages of flexible arrays
Section 5.2 The task completed by the flexible array in , We will think that using an integer pointer in the structure can also accomplish the same task . It is true , Let's have a try , And try to find the difference between the two .
Dynamic memory development diagram :
#include <stdio.h>
#include <stdlib.h>
struct S{
int i;
int *arr;
};
int main(){
// First, allocate a structure size space in dynamic memory
struct S* p = (struct S*)malloc(sizeof(struct S));
// Check p Whether it is a null pointer
if(p == NULL){
printf("%s\n", strerror(errno));
return 1;
}
// Then dynamically allocate the memory space pointed to by the integer pointer in the structure
p->arr = (int*)malloc(sizeof(int) * 10);
// Check p Whether it is a null pointer
if(p->arr == NULL){
printf("%s\n", strerror(errno));
return 1;
}
// Use
int i = 0;
for(i=0; i<10; i++){
*(p->arr + i) = i;
}
for(i=0; i<10; i++){
printf("%d ", p->arr[i]);
}
// Release p Points to the dynamically opened memory space and will p Set to null pointer
free(p->arr);
p->arr = NULL;
free(p);
p = NULL;
return 0;
}
Section 5.2 The dynamic development of middle structure and flexible array is carried out in the heap , To achieve the same effect , You need to dynamically open up memory on the heap twice .
The first dynamic development is the size of a structure , Contains a pointer member .
The second dynamic development is the memory pointed to by the pointer member .
Since memory has been dynamically opened up twice on the heap , At the end of use, it is necessary to release the memory dynamically opened twice . And the two dynamic developments have a certain inclusive relationship , So pay attention to the order of release , Open up first and release later , The later ones are released first .
Because if you release the memory you opened for the first time , Then the memory of the pointer member is recycled . At this time, it's hard to say what the pointer stores , It is not necessarily the starting address of the second dynamic space . At this time, releasing the memory pointed to by the pointer member is illegal access .
Running results :
Advantages of flexible arrays
- Convenient memory release
Flexible arrays only need to be opened up once when dynamically opening up memory , You only need to release it once . It's very convenient .
- Can improve access speed
Continuous memory is good for improving access speed , It also helps reduce memory fragmentation .
Conclusion
This paper mainly introduces the functions in dynamic memory management
malloc()、calloc()、realloc()And how to use it ; Then it introduces the possible problems in the development and use of dynamic memory ; Finally, the concept of flexible array is introduced , Although it is not often used , But there is still corresponding use space .
END
边栏推荐
- CAS操作
- Open source, innovators win, 2022 "science and innovation China" open source innovation list selection is fully open!
- Practical operation: elegant downtime under large-scale micro service architecture
- P1048 [NOIP2005 普及组 T3] 采药
- If there is complex select nesting in the SQL of the flick CDC, when it encounters the binlog of delete, it will
- How to reverse a stack with recursive functions and stack operations only
- A fast method of data set enhancement for deep learning
- 轮询、中断、DMA和通道
- Leetcode (Sword finger offer) - 04. search in two-dimensional array
- Uiautomator2 common commands
猜你喜欢
![[unity introduction program] basic concepts -2d rigid body 2D](/img/67/537e9935bb0f2539945032cadcf232.png)
[unity introduction program] basic concepts -2d rigid body 2D

Nano data, football data, football match scores, sports data API, Qatar world cup

【Unity入门计划】基本概念-预制件 Prefab

Pricing is arbitrary, products are difficult to distinguish between true and false, and platforms are running away. Will the Tibetan market continue to be popular?

Open source, innovators win, 2022 "science and innovation China" open source innovation list selection is fully open!

Network file storage system (II) practical operation of Minio distributed file system

Didi eta (estimate the travel time)

查看电脑重启次数、原因

Eval and assert one sentence Trojan horse analysis

475-82(230、43、78、79、213、198、1143)
随机推荐
交叉熵计算公式
Gather the wisdom of developers and consolidate the foundation of the database industry
The two Nobel Prize winners became the chief scientist of the sky high price Baijiu of "taishanglaojun holding a dream"
查看电脑重启次数、原因
Science: listening to music can really relieve pain. Chinese scientists reveal the neural mechanism behind it
Learn no when playing 8 | the enterprise saves hundreds of thousands in an instant, just because it uses it
How to do a good job in safety development?
[unity entry plan] interface Introduction (1) -scene view
Learn when playing No 3 | are enterprise learning resources wasted? Learn map one trick to solve!
ACNet:用于图像超分的非对称卷积(附实现code)
while(~scanf(“%d“, &n)) 等价于 while(scanf(“%d“,&n)!=EOF)
475-82(230、43、78、79、213、198、1143)
【Unity入门计划】基本概念-触发器 Trigger
Google Earth engine - Landsat 1985-2020 ecological remote sensing index resi calculation
Tunnel broadcasting and wireless trunking communication broadcasting system - the case of Tiantaishan tunnel
P1086 [NOIP2004 普及组第二题] 花生采摘
【Unity入门计划】界面介绍(2)-Games视图&Hierarchy&Project&Inspector
Network file storage system (III) practice of fastdfs distributed file system
P1047 [NOIP2005 普及组 T2] 校门外的树
C 43. Get UDP available ports