目录
一.前言
二.动态内存函数详解及其使用
2.1 malloc和free函数概述
2.1.1 malloc示例使用:
2.2 calloc函数概述
2.2.1 calloc示例使用
2.3 realloc函数概述
2.3.1 realloc函数的示例使用
2.4 动态内存开辟空间中的常见错误
三.常见笔试题
3.1 传参问题的笔试题
3.2 返回栈空间的地址的问题
3.3 造成内存泄漏问题
我们之前编程时创建的一些变量,你知道它们都是存放在内存的哪里吗?
其实,不同的类型的变量在内存中存储的位置是不一样的。
一起来看一下:
那么为什么要有动态内存开辟这一说呢?
有时候我们需要的空间大小在程序运行的时候才能知道,那数组在编译时开辟空间的方式就不能满足了,这时候就需要我们的动态内存分配了。
动态内存开辟主要要求我们了解和掌握四个函数
1.malloc
2.calloc
3.realloc
4.free
1. malloc函数:(文档地址:cplusplus.com)。
2. free函数
#include<stdlib.h> #include<string.h> #include<errno.h> #include<stdio.h> int main() { int* p = (int *)malloc(10 * sizeof(int)); //如果开辟失败 //一定要去检查 if(p == NULL) { //打印错误原因 printf("%s\n",strerror(errno)); } else { //正常使用空间 int i = 0; for(i = 0 ; i < 10 ; i++) { *(p+i) = i; } for(i = 0 ; i < 10 ; i++) { printf("%d\n",*(p+i)); } } //当动态申请的空间不再使用的时候,就应该把空间还给操作系统 free(p);//主动回收掉 p = NULL; return 0; }
剖析代码:
如果,我将开辟的内存空间搞得很大,那么将会返回什么错误信息呢?
其实操作系统是会在我们程序结束的时候,将动态内存开辟的空间释放掉的,那么free函数还有存在的必要吗?
当然!!
怎么样,到这里是不是对malloc和free函数的理解清楚了很多呢?
int main() { int* p = calloc(10,sizeof(int)); if(p == NULL) { //打印错误原因 printf("%s\n",strerror(errno)); } else { int i = 0; for(i = 0 ; i < 10 ; i++) { printf("%d ",*(p+i)); } } free(p); p = NULL; }
代码剖析:
可以根据自己的实际需求来选择使用malloc函数还是calloc函数。
int main() { int* p = (int *)malloc(5 * sizeof(int)); if (p == NULL) { printf("%s\n", strerror(errno)); } else { int i = 0; for (i = 0; i < 5; i++) { *(p + i) = i; } for (i = 0; i < 5; i++) { printf("%d ", *(p + i)); } } printf("\n"); //这里我想在开辟20个空间给我使用 int* p2 = (int *)realloc(p, 5* sizeof(int )); if(p2 != NULL) //追加成功 { p = p2; } int i = 0; for (i = 5; i < 10; i++) { *(p + i) = i; } for (i = 5; i < 10; i++) { printf("%d ", *(p + i)); } free(p); p = NULL; return 0; }
代码剖析:
思考一下:
1.对空指针进行解引用操作
这个错误不用多作介绍,空指针(NULL)当然是不能进行解引用操作的
2.对动态开辟的内存越界访问
上端代码感受一下这个错误
int *p = (int *)malloc*(5 *sizoef(int)); if(p == NULL) { return 0; } else { for(int i = 0 ; i < 10 ; i++) { *(p+i) = i; } free(p); p=NULL; }
这里的错误很明显了,明明只开辟了五个空间,你缺要访问十个,有点过分呀~。
3.对非动态开辟的内存进行free操作
int main() { int p = 10; free(p); }
p在这里不是动态开辟的,如果用free释放是会报错的。
4.对同一块儿动态内存多次释放。
void GetMemory(char *p) { p = (char *)malloc(100 *sizeof(int )); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str,"Hello World!\n"); printf(str); } int main() { Test(); return 0; }
上面的这段代码会不会正确输出呢?
很明显,这里没有输出“Hello World!”,
这段代码是有问题的。
那么问题出在哪里呢?
所以,这里也就很好的证明,为什么程序运行后没有输出。
那么怎么改正它呢?
还记得嘛?传值不行的时候我们可以传址过去。
成功运行
void GetMemory(char **p) { *p = (char *)malloc(100 * sizeof(int)); } void Test(void) { char *str = NULL; GetMemory(&str); strcpy(str, "Hello World!\n"); printf(str); free(str); str = NULL; } int main() { Test(); return 0; }
大家记得把动态开辟的空间释放以及要把指针置空。
char *GetMemory(void) { char p[] = "hello world"; return p; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); } int main() { Test(); return 0; }
这段代码会顺利的打印“Hello World!”吗?
一起来看看。
我去,这是个什么玩意儿?为什么会打印出来这么个鬼东西?
别急,我们一起来看看吧
所以,这里返回的东西我们没有人知道会是什么。
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; }
这段代码有没有问题呢?
正确的打印出来了。
但是,打印出来就没有问题了嘛?
所以,我们写free函数之后,都要将这个指针顺便置为空(NULL)。以防止这种不规范的行为造成不可挽回的后果。
void Test(void) { char *str = (char *)malloc(100); strcpy(str, "hello"); free(str); str = NULL; if (str != NULL) { strcpy(str, "world"); printf(str); } } int main() { Test(); return 0; }
over~~~