Understanding and using c pointers 第二章读书笔记

来源:互联网 发布:centos yum jdk1.8 编辑:程序博客网 时间:2024/04/27 22:56


tonybai在他的网站上写了一个本书的知识点纲要

第二章 C语言中的动态内存管理C99引入了可变长度数组(VLAs),数组长度在运行时决定,然而一旦创建后数组就不会再改变其长度。C语言中的动态内存管理分为如下几步:1.使用malloc函数分配内存2.使用这块内存来做点事情3.完后使用free函数回收分配的内存如下:int *pi = (int*) malloc(sizeof(int));*pi = 5;printf("*pi,%d\n",*pi);free(pi);常见错误的方式如下int *pi,*pi = (int *) malloc(sizeof(int));*pi是指针pi所指向的地址里存贮的值,此时指针pi还没有初始化,很可能发生错误正确的应该是pi = (int*) malloc(sizeof(int));内存释放后不应该再访问,但是有时候还是会无意访问,最好在释放内存后将指针置为NULL当内存分配后,有关附加信息作为数据结构的一部分由堆管理器维护。这些信息包括内存块大小等信息,它们通常被放置在紧邻所分配的内存块,如果应用程序越界访问该内存块,则原有的数据结构可能会被破坏掉,导致程序运行不正常运行或崩溃,比如下面的例子char *pc = (char*)malloc(5 + 1);for(int i = 0; i < 8; i++){*pc[i] = 0;}上述例子是要申请一个5个char的字符串+1是表示字符串结束符NUL,但是for循环进行了8次,越界访问了。内存泄露1.只分配,没回收char *chunck;while(1){chunck = (char*)malloc(1000000);printf("Allocating\n");}2.地址丢失int *pi = (int *) malloc(sizeof(int));*pi = 5;...//内存泄露,之前分配的还没有回收,指针值却改变指向了另外一块内存,之前分配的没被回收pi = (int *) malloc(sizeof(int));char *name = (char *) malloc(strlen("susan") + 1);strcpy(name,"susan");while(*name != 0){printf("%c\n", *name);name++;//name++破坏了原有内存块的地址,造成了内存内存泄露}回收由struct定义的结构时也可能发生内存泄露,如果结构含有动态分配的内存,那么在回收结构之前先要将这些动态分配的内存释放动态内存分配函数在大多数的系上,stdlib.h包里的头文件定义了如下动态内存分配函数malloc 从堆分配内存realloc 根据之前分配的内存块大小,重新分配更大或者更小的内存块calloc 从堆中分配内存并将将分配的内存块全部置零 (allocates and zero out memory from the heap)free 将内存块返还给堆malloc函数原型如下:void* malloc(size_t);所以传递参数时要特别注意不能传负数,因为size_t是一个无符号数,很多系统上传负数会返回NULL指针,我在gcc上测试是这样的。传递0的话会根据系统而不同,有的会返回NULL有的会返回一个指向0字节的指针you cannot use a function call when initializing a static or global variable.In the following code sequence,we declare a staticvariable and then attempt fo initiazlize it using malloc:static int *pi = malloc(sizeof(int));this will generate a compiler-time error message.对于静态变量,像上面直接初始化,编译器会报错(gcc)但是分开就ok 如下:static int *pi;pi = malloc(sizeof(int));对于全局变量,直接初始化与分开初始化都会报错calloc函数原型如下:void *calloc(size_t numElements,size_t elementSize);使用方式如下:int *pi = calloc(5,sizeof(int));使用malloc和memset能够达到同样的效果如下:int *pi = malloc(sizeof(int) * 5);memset(pi,0,5 * sizeof(int));/-calloc可能要被malloc慢一些realloc函数原型如下void *realloc(void *ptr,size_t size);根据参数不同,其结果调用如下


free函数原型如下void free(void *ptr);如果给free传递null指针,则什么也不做如果传递的指针不是malloc类型的函数分配的指针,那么该函数的行为是不确定的。如下,pi被赋予了num的地址,然而它不是一个合法的堆地址int num;int *pi = #free(pi); //undefined behaviour重复释放的同一块内存会造成异常如下int *pi = (int *) malloc(sizeof(int));*pi = 5;free(pi);...free(pi);或者p1 = (int *) malloc(sizeof(int));int *p2 = p1;free(p1);...free(p2);//这种其实也是多次释放,作者叫指针别名当两个指针指向相同的地址,it is referred to as aliasing.堆管理器无需将free掉的内存返还给操作系统,回收的内存可能会被应用程序再次使用悬挂指针问题:内存访问时的不确定行为内存不可访问时造成段错误潜在的安全问题悬挂指针例子:int *pi = (int*) malloc(sizeof(int));*pi = 5;printf("*pi: %d\n", *pi);free(pi);//pi依然指向int变量的地址int *p1 = (int *)malloc(sizeof(int));*p1 = 5;...int *p2;p2 = p1;...free(p1);...*p2 = 10; //悬挂指针代码块声明也能造成悬挂指针int *pi;...{int tmp = 5;pi = &tmp;}//pi现在成了悬挂指针,因为上述大括号代码块执行完毕后就弹出了程序栈foo();处理悬挂指针1.内存释放后将指针置为NULL,但这不能解决指针别名带来的问题2.编写代替free函数的函数3.使用特殊值如VS里的0xCC,0xCD等等4.使用第三方工具


原创粉丝点击