1、经典的C动态内存管理相关函数
标准C提供了malloc, calloc, realloc, free等基于内存堆的管理函数,负责分配可用内存以及释放用过的内存。这些函数本身只负责告诉调用程序,当前有你想要size大小的可用内存块,它的首地址是xxxxx,并不会检查指针的使用是否越过了这个size或者说是offset,这个需要程序员自己去检查。
1 2 3 | #include <stdlib.h> void *malloc(size_t size); |
malloc的作用分配一块大小为size个字节的可用内存块,并返回首地址。不能分配的时候返回NULL。
1 2 3 | #include <stdlib.h> void calloc(size_t nmemb, size_t size); |
calloc的作用是分配并初始化内存块,返回一个指向nmemb块数组的指针,每块大小为size个字节。它和malloc的主要不同之处是会初始化(清零)分配到的内存。
1 2 3 | #include <stdlib.h> void *realloc(void *ptr, size_t size); |
realloc以ptr所指地址为首址,分配size个字节的内存,并返回ptr所指地址。realloc不会初始化分配到的内存块,如果ptr为NULL则相当于malloc,如果size为NULL则相当于free(ptr)。不能分配返回NULL。
1 2 3 | #include <stdlib.h> void free(void *ptr); |
free清除ptr所指向的地址,它只作清除的工作,并告诉系统,这块地址已经被释放和清除,可以重新被分配。
一个带bug的程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /* * mallocfree.c - try to access illegally an address has wrong allocated */ #include <stdlib.h> #include <stdio.h> #include <string.h> int main(void) { char *ptr = malloc(sizeof(char) * 5); strcpy(ptr, "123456789"); printf("ptr : %sn", ptr); printf("freeing ptrn"); free(ptr); sleep(1); printf("ptr : %sn", ptr); printf("trying to write the address has freedn"); strcpy(ptr, "54321"); sleep(1); printf("ptr : %sn", ptr); return 0; } |
sleep函数在里面是为了让肉眼更直观的分析程序的运行。执行make mallocfree,生成可执行文件,并运行之:
ptr : 123456789
freeing ptr
ptr :
trying to write the address has freed
ptr : 54321
在这里,ptr使用的地址已经越过了malloc分配给它的界限,而且指针在释放以后继续使用,这导致缓冲区溢出的隐患。



