潍坊网站制作工具,办网站用什么证件,做网站的怎样能翻页,郑州做网站优化价格文章目录 一、为什么会有动态内存管理二、申请内存函数1、malloc2、free3、calloc4、realloc 三、常见的动态内存的错误四、练习 一、为什么会有动态内存管理
1.我们一般的开辟空间方式#xff1a;
int a 0;//申请4个字节空间
int arr[10] { 0 };//申请40个字节空间2.这样… 文章目录 一、为什么会有动态内存管理二、申请内存函数1、malloc2、free3、calloc4、realloc 三、常见的动态内存的错误四、练习 一、为什么会有动态内存管理
1.我们一般的开辟空间方式
int a 0;//申请4个字节空间
int arr[10] { 0 };//申请40个字节空间2.这样开辟空间的特点 1申请的空间大小是固定的 2像数组那样一开始就要确定大小一旦确定大小就不能改变了 3.动态内存 对于程序来说上述的内存申请是不能满足 因此为了能够对内存进行调整C语言引入了动态内存开辟让程序员自己可以申请和释放空间就比较灵活了。 二、申请内存函数
以下动态申请的内存都是向堆区申请的 并且都申请内存的函数和释放函数都包含在头文件 #includestdlib.h
1、malloc
1返回类型和参数
void* malloc(size_t size);//返回类型为 void* 参数为正整数单位是字节因为返回类型为 void*所以在malloc函数是不知道我们想要申请什么类型的空间面对这种情况我们要将返回的类型进行强制类型转换这样就能返回我们需要的类型了参数是申请的大小 2作用 向内存申请一块连续的空间并返回指向这块空间的的指针 3注意 a.在申请完之后我们还要判断是否成功申请 当申请失败时会返回NULL 当申请成功后就返回指向这块空间的的指针这样可以正常使用这块空间了 b.如果参数 size 为0malloc的行为是标准是未定义的取决于编译器 4使用
int main() {int* p (int*)malloc(sizeof(int) * 10);//向内存申请40个字节空间if (p NULL)//判断是否申请成功return 1;//失败直接放回for (int i 0; i 10; i)//成功就正常使用*(p i) i;for (int i 0; i 10; i)//打印printf(%d , *(p i));return 0;
}运行结果
2、free
1返回类型和参数
void free( void* p)//参数为向动态内存申请的空间的指针返回类型为空2作用 专门进行对动态内存的释放和回收 3注意 a.当释放的内存不是动态开辟的这是free未定义的 b.当p是NULL时free函数什么事都不发生 c.当我们将p指向的空间释放后要将p置空不然p就成野指针了 4使用 在我们上一个代码中并未对malloc函数开辟的空间进行释放其实这是不对的这会造成内存泄漏。 那么我们就来用一下free函数吧 int main() {int* p (int*)malloc(sizeof(int) * 10);//向内存申请40个字节空间if (p NULL)//判断是否申请成功return 1;//失败直接放回for (int i 0; i 10; i)//成功就正常使用*(p i) i;for (int i 0; i 10; i)//打印printf(%d , *(p i));free(p);//释放p NULL;//及时置空防止出现野指针return 0;
}这样代码才算完整。
3、calloc
1返回类型和参数
void *calloc(size_t n,size_t size);返回类型为 void* 所以和malloc一样想要什么类型的空间就进行强制转换类型即可第一个参数为申请的个数第二个参数为申请的类型的空间大小单位为字节 2作用 申请一块连续的空间并将空间的内容全部初始化为0然后返回指向这块空间的指针 (3)注意 a.在申请完之后我们还要判断是否成功申请 当申请失败时会返回NULL 当申请成功后就返回指向这块空间的的指针这样可以正常使用这块空间了 b.如果参数 size 为0malloc的行为是标准是未定义的取决于编译器 c.与malloc的区别就是calloc会将申请的空间初始化这样使用时更方便 4使用
int main() {int* p (int*)calloc(10,sizeof(int));//申请if (p NULL) {//判断printf(NULL);return 1;}//使用for (int i 0; i 10; i)*(p i) i;for (int i 0; i 10; i)printf(%d , *(p i));free(p);//同样的释放空间p NULL;//置空return 0;
}运行结果
4、realloc
1返回类型和参数
void *realloc(void * p ,size_t size);返回类型为 void* 所以和calloc一样想要什么类型就强制类型转换第一个参数p为指向想要的改变的空间的 指针第二参数为改变的大小单位为字节 2作用 在原来的动态内存的空间上增大或者缩小并返回改变后指向新的空间的指针 3注意 a.开辟失败返回空指针 b.开辟的新的空间时有两种开辟的方式第一种是我们原本的空间后面有足够的空间那样直接在原来的空间后面扩容第二种是我们原本的空间后面没有足够的空间那样的话系统就会在内存上找一块适合的空间重新开辟并将原来空间的内容复杂过去再将原来的空间销毁。 由于开辟的情况有两种所以我们使用时要注意开辟空间失败这种情况 如我们使用了第二种情况开辟空间、并直接用原来的指针去接收指向开辟的空间的指针如果开辟失败的话返回NULL这导致原来的数据会丢失。 所以为了解决这个隐患我们可以重新定义一个指针来接收判断不为空再将该指针赋给原来的指针。 图 4使用
int main() {//先用动态内存开辟一个空间int* p (int*)calloc(10, sizeof(int));if (p NULL)return 1;for (int i 0; i 10; i)*(p i) i;for (int i 0; i 10; i)printf(%d , *(p i));printf(\n);//使用realloc增加空间int* pp (int*)realloc(p, sizeof(int) * 15);//再申请一个指针变量来接收if (pp NULL)return 1;elsep pp;//不为空再赋给原来的指针for (int i 10; i 15; i)*(p i) i;for (int i 10; i 15; i)printf(%d , *(p i));free(p);//最后不要忘记了释放并置空p NULL;return 0;
}运行结果
三、常见的动态内存的错误
1、对NULL指针的解引用操作
void test(){int *p (int *)malloc(INT_MAX/4);//开辟空间//这里我们不知道是否开辟成功*p 20;//如果p的值是NULL就会有问题free(p);pNULL;}这里的问题是不知道p为不为NULL 改
void test(){int *p (int *)malloc(INT_MAX/4);//开辟空间if(p!NULL)*p 20;free(p);pNULL;}2 、对动态开辟空间的越界访问
void test(){int i 0;int *p (int *)malloc(10*sizeof(int));if(NULL p){exit(EXIT_FAILURE);}for(i0; i10; i){*(pi) i;//当i是10的时候越界访问}free(p);pNULL;}改
void test(){int i 0;int *p (int *)malloc(10*sizeof(int));if(NULL p){exit(EXIT_FAILURE);}for(i0; i10; i)//当我们改成10之后i就不会到10也就不会越界了{*(pi) i;}free(p);pNULL;}3 、对非动态开辟内存使用free释放 void test(){int a 10;int *p a;free(p);//ok?}这种行为在free函数中未定义最好不要使用 4 、使用free释放⼀块动态开辟内存的⼀部分
void test(){int *p (int *)malloc(100);p;free(p);//p不再指向动态内存的起始位置}这种行为会导致内存泄漏 5 、对同⼀块动态内存多次释放
void test(){int *p (int *)malloc(100);free(p);free(p);//重复释放}当出现这种情况程序会崩掉 6、 动态开辟内存忘记释放内存泄漏
void test(){int *p (int *)malloc(100);if(NULL ! p){*p 20;}}
int main(){test();while(1);}这种未对申请的空间释放会导致内存泄漏
四、练习
1、请问运行Test 函数会有什么样的结果
void GetMemory(char *p){p (char *)malloc(100);}
void Test(void){char *str NULL;GetMemory(str);strcpy(str, hello world);printf(str);}运行结果 什么都没有输出这是为什么呢 这是因为调用GetMemory函数时使用的是传值调用p虽然申请到了空间但是并没有改变str的值所以strNULL所以什么内容都没有打印 改;我们可以将传值调用改为传址调用 如
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;
}运行结果 成功打印 2、请问运行Test 函数会有什么样的结果
char *GetMemory(void){char p[] hello world;return p;}
void Test(void){char *str NULL;str GetMemory();printf(str);}运行结果 出现了随机值这是为什么呢? 因为p是在栈区创建当函数结束后该p指向的空间也会销毁然后返还给内存此时将p传给str之后str就会变成野指针它指向的空间打印出来的就是随机值了 改我们可以用动态内存 如
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;
}运行结果 3、请问运行Test 函数会有什么样的结果
void GetMemory(char **p, int num){*p (char *)malloc(num);}
void Test(void){char *str NULL;GetMemory(str, 100);strcpy(str, hello);printf(str);}运行结果 输出正确。但是这里的问题时没有释放动态内存 改
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;
}4、请问运行Test 函数会有什么样的结果
void Test(void){char *str (char *) malloc(100);strcpy(str, hello);free(str);if(str ! NULL){strcpy(str, world);printf(str);}}运行结果 虽然结果正确但是其实是有问题的 1.因为str存储的地址不会改变应该手动置空但是它释放空间后没有置空 2.使用释放的空间这块空间已经还给系统了 3.为什么还能打印world呢那是因为该块空间没有被覆盖world还在那里 我们可以试试再他前面再申请一次动态内存看看
void Test(void)
{char* str (char*)malloc(100);strcpy(str, hello);free(str);if (str ! NULL){strcpy(str, world);char* str1 (char*)malloc(100);printf(str);}
}
int main() {Test();return 0;
}运行结果 world被覆盖了就打印不出了 改我们可以释放后置空就不会出现这种情况了
void Test(void){char *str (char *) malloc(100);strcpy(str, hello);free(str);strNULLif(str ! NULL){strcpy(str, world);printf(str);}}以上就是我的分享了如果有什么错误欢迎在评论区留言。 最后谢谢大家的观看