动态内存管理

张开发
2026/5/18 1:38:30 15 分钟阅读
动态内存管理
目录1.为什么要有动态内存分配2.malloc和free3.calloc和realloc4.常见的动态内存的错误5.动态内存经典笔试题分析1.为什么要有动态内存分配我们目前已经掌握的内存开辟的方式有int val20;//在栈空间开辟四个字节 char arr[10]{0};//在栈空间上开辟10个字节的连续空间但是上述开辟空间的方式有两个特点1.空间的开辟大小是固定的。2.数组在声明的时候必须要指定数组的长度数组的空间一旦确定了大小就不能不改变了。但是对于空间的要求不仅仅是上述的情况。有时候我们需要的空间大小需要再程序运行的过程中才能知道那么数组的编译时开辟的空间的方式就不能被满足了。2.malloc和free2.1 mallocC语言提供了一个动态内存开辟的函数void *malloc(size_t size);//单位是字节这个函数向内存申请⼀块连续可⽤的空间并返回指向这块空间的指针。•如果开辟成功则返回⼀个指向开辟好空间的指针。•如果开辟失败则返回⼀个NULL指针因此malloc的返回值⼀定要做检查。•返回值的类型是void*所以malloc函数并不知道开辟空间的类型具体在使⽤的时候使⽤者⾃⼰来决定。•如果参数size为0malloc的⾏为是标准是未定义的取觉与编译器。#includestdio.h #includestdlib.h int main() { int* p (int*)malloc(4 * sizeof(int));//malloc是void*返回int时要强制类型转换这样方便访问整型是一下跳过4个字节 if (p NULL) { perror(malloc); return 1; } //后续还要对其进行释放 int i 0; for (i 0; i 5; i) { *(p i) i1; } return 0; }2.2 freeC语言提供了另一个函数是free专门用来对动态内存的释放和回收的void free(void * ptr)free函数⽤来释放动态开辟的内存。•如果参数ptr指向的空间不是动态开辟的那free函数的⾏为是未定义的。•如果参数ptr是NULL指针则函数什么事都不做。malloc和free都声明在stdlib.h头⽂件中。#includestdio.h #includestdlib.h int main() { int num 5; int* ptr NULL; ptr (int*)malloc(num * sizeof(int)); if (ptr NULL) { perror(malloc); return 1; } else { int i 0; for (int i 0; i num; i) { *(ptr i) 0; } free(ptr); ptr NULL; return 0; } }3.calloc和realloc3.1 callocvoid *calloc(size_t num,size_t size);函数的功能是为num个⼤⼩为size的元素开辟⼀块空间并且把空间的每个字节初始化为0。与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全为0。#includestdio.h #includestdlib.h int main() { int* p (int*)calloc(10, sizeof(int)); if (p NULL) { perror(calloc); } else { int i 0; for (int i 0; i 10; i) { printf(%d , *(p i)); } } free(p); p NULL; return 0; }3.2 reallocrealloc函数的出现让动态内存管理更加灵活。有时会我们发现过去申请的空间太⼩了有时候我们⼜会觉得申请的空间过⼤了那为了合理的时候内存我们⼀定会对内存的⼤⼩做灵活的调整。那realloc函数就可以做到对动态开辟内存⼤⼩的调整。void *reallo(void *ptr,size_t size);ptr是要调整的内存地址size调整之后新⼤⼩返回值为调整之后的内存起始位置。这个函数调整原内存空间⼤⼩的基础上还会将原来内存中的数据移动到 新 的空间。realloc在调整内存空间的是存在两种情况情况1原有空间之后有⾜够⼤的空间情况2原有空间之后没有⾜够⼤的空间\#includestdio.h #includestdlib.h int main() { int* ptr (int*)malloc(100); if (ptr ! NULL) { //业务处理 } else { return 1; } //代码1-直接将realloc的值放回值到ptr中 ptr (int*)realloc(ptr, 100); //代码2-先将realloc函数的返回值放到p中。不分NULL在放ptr int* p NULL; p realloc(ptr, 100); if (p ! NULL) { ptr p; } free(ptr); return 0; }4.常见的动态内存的错误4.1 对NULL指针的解引用操作void test() { int* p (int*)malloc(INT_MAX / 4); *p 20; free(p); }没有判断p是否为空如果p为空的话就会出现错误正确代码如下void test() { int* p (int*)malloc(INT_MAX / 4); if (p NULL) { perror(p); return 1; } else { *p 20; } free(p); }4.2 对动态开辟空间进行越界访问void test() { int i 0; int* p (int*)malloc(10 * sizeof(int)); if (p NULL) { exit(p); } else { for (int i 0; i 10; i) { *(p i) i; } free(p); } }当i等于10时越界访问了正确代码如下void test() { int i 0; int* p (int*)malloc(10 * sizeof(int)); if (p NULL) { exit(p); } else { for (int i 0; i 10; i) { *(p i) i; } free(p); } }4.3 对非动态开辟内存使用free释放void test() { int a 10; int* p a; free(p); }都不是动态内存分配不可以用free。4.4 使用free释放一块动态开辟内存的一部分void test() { int* p (int*)malloc(100); p; free(p); }p的原始地址被换走找不到最初的地址了。正确写法如下int test() { int* p (int*)malloc(100); if (p NULL) { return 1; } else { for (int i 0; i 5; i) { *p p i; p; } } free(p); p NULL; }4.5 对同一块动态内存多次释放void test() { int* p (int*)malloc(100); free(p); free(p); }重复释放动态内存正确写法如下void test() { int* p (int*)malloc(100); free(p); }4.6 动态开辟内存忘记释放 内存泄漏void test() { int* p (int*)malloc(100); if (NULL ! p) { *p 20; } } int main() { test(); while (1); }申请动态函数是没有释放忘记释放不再使用的动态开辟的空间会造成内存泄漏。如果没有使用free来释放的话操作系统自己回释放的。我们要尽量做到1.谁申请的空间谁释放。2.如果不能释放的话要告诉使用的人记得释放。正确写法如下void test() { int* p (int*)malloc(100); int n 3; if (n 3) { return; } free(p); p NULL; } int main() { test(); while (1); }5.动态内存经典笔试题分析5.1 题目1void GetMemory(char* p) { p (char*)malloc(100); } void Test(void) { char* str NULL; GetMemory(str); strcpy(str, hellp world); printf(str); }存在俩个问题1.内存泄漏有malloc无free 2.程序崩溃str是空指针传给p时p也是一个空指针给p动态100个字节然后p回到GetMary中而此时函数原来的地址被编译器给销毁了找不到原来地址此时函数越界程序崩溃。正确写法如下void GetMemory(char** p) { *p (char*)malloc(100); } void Test(void) { char* str NULL; GetMemory(str); strcpy(str, hellp world); printf(str); free(str); str NULL; }5.2 题目2char* GetMemory(void) { char p[] hello world; return p; } void Test(void) { char* str NULL; str Getmemory(); printf(str); }等Getmemory函数返回后使用str指针去访问p数组就是非法访问因为p数组的内存已经还给了操作系统。str是野指针.5.3 题目3void GetMeory(char** p, int num) { *p (char*)malloc(num); } void Test() { char* str NULL; GetMeory(str, 100); strcpy(str, hello); printf(str); }动态存储无free5.4 题目4void Test(void) { char* str (char*)malloc(100); strcpy(str, hello); free(str); if (str ! NULL) { strcpy(str, world); printf(str); } }动态存储无free

更多文章