当前位置:网站首页>Dynamic memory management + flexible array
Dynamic memory management + flexible array
2022-07-21 00:43:00 【A Liang joy】
Catalog
The introduction of dynamic memory function
1. Yes NULL Dereference operation of pointer
2. Cross border access to dynamic open space
3. Use of non dynamic memory free Release
4. Use free Release a piece of dynamic memory
5. Multiple releases of the same dynamic memory
6. Dynamic memory forget to release ( Memory leak )
Several classic written examination questions
C/C++ Program memory development
1. The characteristics of flexible arrays
Why is there dynamic memory
The memory development methods we have mastered are :
int val = 20;// Open up four bytes in the stack space
char arr[10] = {0};// Open up on the stack space 10 Bytes of contiguous 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 can only try dynamic storage development .
The introduction of dynamic memory function
1.malloc and free
malloc yes C Language provides a dynamic memory development function , The function prototype is as follows :
void* malloc (size_t size);
malloc The function requests a contiguous available space from memory , And return the pointer to this space . about malloc function , We need to pay attention to a few points :
- If the development is successful , Then return a pointer to open a good space .
- If the development fails , Returns a NULL The pointer , therefore malloc The return value of must be checked .
- The type of return value is void* , therefore malloc Function doesn't know the type of open space , The user will decide when using it .
- If parameters size by 0,malloc The standard is undefined , Depends on the compiler .
C Language provides another function free, It is specially used to release and reclaim dynamically developed memory , The function prototype is as follows :
void free (void* ptr);
about free function , We need to pay attention to a few points :
- If parameters ptr The pointed space is not opened dynamically , that free The behavior of a function is undefined .
- If parameters ptr yes NULL The pointer , Then the function does nothing .
- free Function releases dynamically opened space , Be sure to set the pointer to this space as a null pointer NULL.
Be careful :malloc and free The declarations of functions are in stdlib. h Header file .
Code example :
// Dynamic memory development
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Suppose 10 An integer space
//int arr[10];// The stack area
// Dynamic memory development
int* p = (int*)malloc(10 * sizeof(int));//void*
// When using these spaces
if (p == NULL)
{
//strerror Convert error codes into error messages
perror("main");// Print error messages main:×××××× for example : Insufficient space for development failure
return 0;
}
// Use
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", p[i]);//p[i]<==>*(p+i)
}
// Recycle space
free(p);
p = NULL;// Do it yourself p Set to null pointer
return 0;
}
The above code has two points to pay attention to : First of all , After applying for dynamic memory , Be sure to determine whether the pointer to the space is a null pointer NULL. Because when dynamic memory development fails ,malloc The function returns a null pointer NULL. second , use free Function releases and reclaims dynamically opened memory , Be sure to set the pointer to the space as a null pointer NULL. Because the pointer also remembers the address of this space , If you dereference the pointer , It will cause the problem of wild pointer .
After knowing this , Let's take another look at the code .
Code example :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a = 10;
int* p = &a;
free(p);//err
return 0;
}
Be careful : The above code is an error code , The reason is that free Function is used to release memory that is not dynamically opened . When we write code, we must pay attention to ,free Function can only be used to free and reclaim dynamically opened memory , Otherwise the program will crash !!!
2.calloc
except malloc function ,C The language also provides a function calloc,calloc Function can also be used for dynamic memory development . The function prototype is as follows :
void* calloc (size_t num, size_t size);
about calloc function , We need to pay attention to a few points :
- The function is for num Size is size The elements of open up a space , And initialize each byte of the space to 0.
- And malloc The difference between functions is calloc There are two arguments to the function , and malloc The function has only one argument ; And that is calloc The function initializes each byte of the requested space to full... Before returning the address 0.
Code example :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL)
{
perror("main");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
free(p);
p = NULL;
return 0;
}
therefore , If we need to initialize the contents of the requested memory space , So use calloc Function can easily complete the task .
3.realloc
realloc Functions make dynamic memory management more flexible . Sometimes we find that the application space is too small in the past , Sometimes we think the application space is too large , That's for reasonable time memory , We will make flexible adjustments to the size of memory . and realloc Function can be used to adjust the dynamic memory size . The function prototype is as follows :
void* realloc (void* ptr, size_t size);
about realloc function , We need to pay attention to a few points :
- ptr Is the memory address to be adjusted .
- size For the new size after adjustment .
- The return value is the starting memory position after adjustment .
- This function adjusts the size of the original memory space , It will also move the data in the original memory to a new space .
- realloc There are two ways to adjust memory space :
- situation 1: There is enough space behind the original space .
- situation 2: There is not enough space after the original space .
situation 1:
When it's the case 1 When , To expand memory, add space directly after the original memory , The original spatial data does not change .
situation 2:
When it's the case 2 When , When there is not enough space after the original space , The way to expand is : In the heap space to find another suitable size of continuous space to use . This function returns a new memory address .
Because of the above two situations ,realloc We should pay attention to the use of functions .
Code example :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)calloc(10,sizeof(int));
if (p == NULL)
{
perror("main");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
// Need here p Point to more space , need 20 individual int Space
//relloc Adjust the space
int* ptr = (int*)realloc(p, 20 * sizeof(int));// prevent p Set to null pointer
if (ptr != NULL)
{
p = ptr;
}
for (i = 10; i < 20; i++)
{
*(p + i) = i;
}
// Change the size of the application space , Observe p Will your address change
free(p);
p = NULL;
return 0;
}
Case 2 code example :
Another thing to note is ,realloc Functions can also act as malloc Function to use .
int* p = (int*)realloc(NULL, 10 * sizeof(int));
<= = > int* p = (int*)malloc(10 * sizeof(int));
I believe you already know realloc Function , Next, let's introduce the common dynamic memory errors .
Common dynamic memory errors
1. Yes NULL Dereference operation of pointer
int main()
{
int* p = (int*)malloc(100000000000000000);
// error : Not right malloc Judge the return value of the function , Just dereference
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
return 0;
}
modify :
int main()
{
int* p = (int*)malloc(100000000000000000);
// error : Not right malloc Judge the return value of the function , Just dereference
if (p == NULL)
{
perror("main");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
return 0;
}
2. Cross border access to dynamic open space
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
// A cross-border visit
for (i = 0; i < 40; i++)
{
*(p + i) = i;
}
free(p);
p = NULL;
return 0;
}
modify :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
// A cross-border visit
for (i = 0; i < 10; i++)
{
*(p + i) = i;
}
free(p);
p = NULL;
return 0;
}
3. Use of non dynamic memory free Release
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
// Use
// Release
free(p);
p = NULL;
return 0;
}
4. Use free Release a piece of dynamic memory
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
return 1;
}
int i = 0;
for (i = 0; i < 5; i++)
{
*p++ = i;
}
free(p);//p No longer points to the start of dynamic memory
//
p = NULL;
}
Be careful :free The released dynamic memory space must be the starting address of the space , Otherwise the program will crash .
5. Multiple releases of the same dynamic memory
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(100);
// Use
// Release
free(p);
//p=NULL; Empty in time
// Release again
free(p);
return 0;
}
Be careful : After releasing the dynamically opened memory , Be sure to set the pointer to the space as a null pointer NULL. Otherwise, it is easy to release the same dynamic memory multiple times , Cause the program to crash .
6. Dynamic memory forget to release ( Memory leak )
#include <stdio.h>
#include <stdlib.h>
void test()
{
int* p = (int*)malloc(100);
if (p == NULL)
{
return;
}
// Use
}
int main()
{
test();
//...
return 0;
}
The above code runs , There will be no mistakes . But forget to release the dynamically opened memory , Will cause memory leaks , In this way, your memory will be less and less . This is a very serious problem , So after using the dynamically opened memory , Be sure to free the memory and empty it in time .
Two recycling methods of dynamically opened space :
- Take the initiative free
- Program end
Several classic written examination questions
Topic 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
Output results :
The code analysis :
modify :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* GetMemory(char* p)
{
p = (char*)malloc(100);
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory(str);
strcpy(str, "hello world");
printf(str);
//printf("hello world"); // It's a character h The address of
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
void GetMemory(char** p)
{
*p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf(str);
//printf("hello world"); // The message is h The address of
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
Topic two
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main()
{
Test();
return 0;
}
Output results :
The code analysis :
Topic three
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
Output results :
The code analysis :
modify :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void GetMemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
Topic four
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
Output results :
The code analysis :
modify :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
// After dynamic internal release, empty it in time
str = NULL;
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
Test();
return 0;
}
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 )(static) 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 .
With this picture , We can better understand static Keywords modify local variables .
In fact, ordinary local variables allocate space in the stack area , The characteristic of stack area is that the variables created above are destroyed when they are out of scope . But be static The modified variables are stored in the data section ( Static zone ), Data segments are characterized by variables created above , Not until the end of the program , So the life cycle gets longer .
Flexible array
Maybe you've never heard of flexible arrays (flexible array) The concept , But it does exist .C99 in , The last element in the structure is allowed to be an array of unknown size , This is called 『 Flexible array 』 member .
for instance :
struct S
{
int n;
int arr[];// The size is unknown
};
Some compilers will report errors and cannot compile. They can be changed to :
struct S
{
int n;
int arr[0];// The size is unknown
};
1. The characteristics of flexible arrays
- A flexible array member in a structure must be preceded by at least one other member .
- sizeof The returned size 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 .
Code example :
#include <stdio.h>
struct S
{
int n;
int arr[0];// The size is unknown
};
int main()
{
struct S s = { 0 };
printf("%d\n", sizeof(s));
return 0;
}
Output results :
2. The use of flexible arrays
Use method 1 :
#include <stdio.h>
#include <stdlib.h>
struct S
{
int n;
int arr[0];// The size is unknown
};
int main()
{
// expect arr Its size is 10 An integer
struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));
ps->n = 10;
int i = 0;
for (i = 0; i < 10; i++)
{
ps->arr[i] = i;
}
// increase capacity
struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));
if (ptr != NULL)
{
ps = ptr;
}
// Use
// Release
free(ps);
ps = NULL;
return 0;
}
Use method 2 :
#include <stdio.h>
#include <stdlib.h>
struct S
{
int n;
int* arr;
};
int main()
{
struct S* ps = (struct S*)malloc(sizeof(struct S));
if (ps == NULL)
return 1;
ps->n = 10;
ps->arr = (int*)malloc(10 * sizeof(int));
if (ps->arr == NULL)
return 1;
int i = 0;
for (i = 0; i < 10; i++)
{
ps->arr[i] = i;
}
for (i = 0; i < 10; i++)
{
printf("%d ", ps->arr[i]);
}
// increase capacity
int* ptr = (int*)realloc(ps->arr, 20 * sizeof(int));
if (ptr != NULL)
{
ps->arr = ptr;
}
// Use
// Release takes two
free(ps->arr);
ps->arr = NULL;
free(ps);
ps = NULL;
return 0;
}
Be careful : The above two methods of use , I recommend the first . Because 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, You can't expect users to discover this . therefore , If we allocate the memory of the structure and the memory of 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 , There is less chance of error . At the same time, the first method can access memory faster , Because continuous memory is beneficial to improve access speed , It also helps reduce memory fragmentation .
That's all about this blog , If you think you've got something , You can support it with a compliment !
边栏推荐
- CCTV news news news channel of Chongqing catering manual tearing quota invoice_ People's network
- The applet "getlocation:fail fail: require permission desc" failed to get the requested address
- 【LeetCode】二分基础模板,查找左右边界
- 苦劝无果,民警现场写代码揭诈骗,这事让我有一个脑洞
- Web performance test needs analysis, what should we do?
- 央视新闻《南京开住宿手撕定额发票》新闻频道_人民网
- 央视新闻《郑州开餐饮手撕定额发票》新闻频道_人民网
- 央视新闻《苏州开住宿手撕定额发票》新闻频道_人民网
- What is the reason why the easycvr video Plaza device list cannot be scrolled and loaded?
- Luogu p1918 bowling ball
猜你喜欢
EasyCVR平台针对360浏览器自动填充密码问题的解决办法
NET问答: C# 中是否有最高效的方式对大文件做 checksum ?
Sweetalert notes - add input box pictures, etc. in the pop-up window
Protocol Buffer 学习
[romance understood by technical talents] tidb community has prepared a "Tanabata Festival" gift for your partner, and everyone has a share!
EasyCVR视频广场设备列表无法滚动和加载是什么原因?
QT_代码
DeiT:注意力也能蒸馏
DBeaver的操作日志
Cve-2014-6271 "broken shell" vulnerability
随机推荐
CCTV news "Chengdu opens catering quota invoice by hand" news channel_ People's network
央视新闻《青岛开餐饮手撕定额发票》新闻频道_人民网
LeetCode-数组中数字出现的次数(单身狗问题)
Create the future and enjoy extraordinary. Opengauss Developer Day 2022 was successfully held
Dest0g3 520 orientation Web
codeforces每日5题(均1500)-第二十天
Why has API strategy become a magic weapon for enterprises' digital transformation?
央视新闻《上海开住宿手撕定额发票》新闻频道_人民网
央视新闻《武汉开住宿手撕定额发票》新闻频道_人民网
苦劝无果,民警现场写代码揭诈骗,这事让我有一个脑洞
CCTV news "Qingdao opens catering quota invoice by hand" news channel_ People's network
For statement range function
Wechat applet development learning 4 (view and logic)
吴恩达-02 改善深层神经网络:超参数调试、正则化以及优化
CCTV news "Hangzhou rent quota invoice by hand" news channel_ People's network
CCTV news "Ningbo opens catering quota invoice by hand" news channel_ People's network
华为(huawei)园区网的常规部署配置示例
XSS cross site scripting attack
开发那些事儿:EasyCVR集群该如何配置参数?
Re understand the life world and ourselves