13深入理解C指针之---内存管理
该系列文章源于《深入理解C指针》的阅读与理解,由于本人的见识和知识的欠缺可能有误,还望大家批评指教。
内存管理对所有程序都很重要,主要包括显式内存管理和隐式内存管理。其中隐式内存管理主要是自动变量分配内存,变量主要分配在函数的栈帧上。若是静态变量或全局变量,主要分配在程序的数据段,能够被自动分配数值。显式内存分配可以更加灵活高效的管理内存,可以有效避免空间浪费。C语言支持动态内存管理,对象从堆上分配内存,使用内存分配函数和内存释放函数实现内存的动态管理。
一、内存分配流程:缺少任何环节都有可能出现问题
1、使用内存分配函数分配内存主要包括malloc、calloc、realloc、alloca等
2、使用分配的内存支持应用程序
3、使用free函数释放内存,将内存空间返还给系统
隐式内存管理代码如下:
1 #include <stdio.h> 2 3 int main(int argc, char **argv) 4 { 5 int var1 = 5; 6 int *ptrVar = &var1; 7 printf("The var1 is %d and address is %p\n", var1, &var1); 8 printf("The *ptrVar is %d and ptrVar is %p and ptrVar address is %p\n", *ptrVar, ptrVar, &ptrVar); 9 10 return 0; 11 }
显式内存管理代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char **argv) 5 { 6 int *var1 = (int *)malloc(sizeof(int)); 7 *var1 = 5; 8 int *ptrVar = var1; 9 printf("The *var1 is %d and var1 is %p and address is %p\n", *var1, var1, &var1); 10 printf("The *ptrVar is %d and ptrVar is %p and ptrVar address is %p\n", *ptrVar, ptrVar, &ptrVar); 11 12 return 0; 13 }
指针使用完毕,记得释放内存,释放内存,释放内存,重要的事情说三遍,否则容易造成内存泄露。
1)、分配内存时,需要自行把握内存空间的大小,否则可以越界访问数据,代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char **argv) 5 { 6 char *pc = (char*)malloc(sizeof(char) * 6); 7 for(int i = 0; i < 18; i++){ 8 pc[i] = 97 + i; 9 } 10 for(int i = 0; i < 18; i++){ 11 printf("%c", pc[i]); 12 } 13 printf("\n"); 14 free(pc); 15 16 return 0; 17 }
上面代码,申请了6个字节的空间,但是可以使用18个字节的字符。
2)、realloc函数的应用,需要自行把握空间的大小,代码如下:
1 /* *=+=+=+=+* *** *=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= 2 * 作者代号: *** :guochaoxxl 3 * 版权声明: *** :(魎魍魅魑)GPL3 4 * 联络信箱: *** :guochaoxxl@gmail.com 5 * 文档用途: *** :深入理解C指针 6 * 文档信息: *** :~/WORKM/StudyCode/CodeStudy/cnblogs_understanding_and_using_c_pointers/chapter2/test12.c 7 * 修订时间: *** :2017年第39周 10月01日 星期日 下午01:32 (274天) 8 * 代码说明: *** :演示realloc函数的使用 9 * *+=+=+=+=* *** *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+*/ 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 int main(int argc, char **argv) 15 { 16 char *arrCh1 = (char *)malloc(sizeof(char) * 8); 17 //arrCh1 = "teacherg"; 18 strcpy(arrCh1, "teacherg"); 19 printf("arrCh1: %p and value: %s\n", arrCh1, arrCh1); 20 21 char *arrCh2 = (char *)realloc(arrCh1, sizeof(char) * 256); 22 if(arrCh2) //只要新的内存arrCh2分配成功,函数realloc会自动释放arrCh1 23 { 24 printf("Memory Reallocated at: %p\n",arrCh2); 25 }else{ 26 printf("Not Enough Memory!/n"); 27 free(arrCh1); //若分配内存失败,则需要手动释放内存,否则内存泄露 28 arrCh1 = NULL; 29 30 return -1; 31 } 32 printf("arrCh1: %p and value: %s\n", arrCh1, arrCh1); //只能获取arrCh1的地址,而无法获取内容 33 strcat(arrCh2, "uo good"); //arrCh2中已包含原来arrCh1中内容,添加新内容 34 printf("arrCh2: %p and value: %s\n", arrCh2, arrCh2); //获取arrCh2的地址和内容 35 free(arrCh2); //释放内存 36 37 return 0; 38 }
需要注意的是:第17行代码虽然和第18行代码的作用看似是一样的,但是在本例中,只能使用第18行,主要是使用字符串赋值是使用常量池,对后面分配内存的环节有影响,可以自行运行下代码,再思考下就会明白。
至于calloc和alloc函数,比较简单,就不罗嗦了。
人就像是被蒙着眼推磨的驴子,生活就像一条鞭子;当鞭子抽到你背上时,你就只能一直往前走,虽然连你也不知道要走到什么时候为止,便一直这么坚持着。