一. C语言内存分布图动态内存管理专指堆heap区代码段存放二进制代码只读运行期间不能修改。数据段.rodata存放着只读数据如字符串常量等。.data存放着已经初始化过的全局/静态变量.bss存放着未被初始化的全局/静态变量系统初始化其为0堆heap内存空间2.9G用户自己申请自己释放动态内存灵活。在程序运行时需要申请空间就在堆区申请。共享区库函数的实现比如scanf、printf等等动态库(共享库)可使用指令ldd ./a.out来查看当程序a.out运行时需要哪些动态库栈stack8M内存空间自动申请自动释放出了作用域内存就会自动释放存放局部变量函数形参函数返回地址等二. 动态内存函数的介绍2.1 malloc函数作用这个函数向内存申请一块连续可用的空间并返回指向这块空间的指针。返回值如果开辟成功则返回一个指向开辟好空间的指针。如果开辟失败则返回一个NULL指针因此malloc的返回值一定要做检查。注意返回值的类型是void*所以malloc函数并不知道开辟空间的类型具体在使用的时候使用者自己来决定。如果参数 size 为0malloc的行为是标准是未定义的取决于编译器。注意对malloc申请的内存空间一定要free不然会内存泄漏。对malloc申请的空间free之后空间中的数据是否还存在若系统内存空间使用紧张则free后的空间立马被使用数据被覆盖。若空间使用不紧张则数据保留不被覆盖。free之后不可对ptr指针指向的空间进行操作。2.2 free函数作用专门用来做动态内存的释放和回收。注意如果参数 ptr 指向的空间不是动态开辟的将会报错。如果参数 ptr 是NULL指针则函数什么事都不做。void fun(char **pp) { *pp (char*)malloc(sizeof(char)*100); } int main(int argc, char **argv) { char *p NULL; fun(p);//要在函数内部修改指针要传二级指针 strcpy(p,hello); printf(p is %s\n,p); free(p100);//malloc之后一定要free防止内存泄漏 //free之后不可对申请的内存的地址进行访问 //归还空间p中依然存放着申请的空间的地址p为野指针不可对此空间进行访问 p NULL;//空指针 return 0; }2.3 calloc函数自带初始化功能作用函数的功能是为 num 个大小为 size 的元素开辟一块空间并且把空间的每个字节初始化为0。与malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。2.4 realloc函数动态扩展空间realloc函数的出现让动态内存管理更加灵活。作用不管申请的空间太小了还是申请的空间过大了为了合理的申请内存会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。参数ptr是要调整的内存地址size调整之后新大小返回值为调整之后的内存起始位置。 失败则返回NULL注意这个函数调整原内存空间大小的基础上还会将原来内存中的数据移动到新的空间。在调整内存空间的是存在两种情况情况1原有空间之后有足够大的空间情况2原有空间之后没有足够大的空间情况一当是情况1的时候要扩展内存就直接原有内存之后直接追加空间原来空间的数据不发生变化情况二当是情况2的时候原有空间之后没有足够多的空间时扩展的方法是在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址还会将原来内存中的数据移动到新的空间并且自动释放旧空间。egint main() { int *ptr (int*)malloc(100); if(ptr ! NULL) { // } else { exit(1); } //扩展容量 int*p NULL;//重新定义一个指针变量 p realloc(ptr, 1000); if(p ! NULL) { ptr p;//如果扩展成功则赋值 } //业务处理 free(ptr); return 0; }三. 常见动态内存的错误3.1 对NULL指针进行解引用操作void test() { int *p (int *)malloc(INT_MAX/4); *p 20;//如果p的值是NULL就会有问题 free(p); }3.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); }3.3 对非动态内存开辟的空间进行free释放void test() { int a 10; int *p a; free(p);//段错误 }3.4 使用free释放动态内存开辟的空间的一部分void test() { int *p (int *)malloc(100); p; free(p);//p不再指向动态内存的起始位置 }3.5 对同一块内存多次释放void test() { int *p (int *)malloc(100); free(p); free(p);//重复释放 }3.6 动态内存忘记释放-内存泄漏void test() { int *p (int *)malloc(100); if(NULL ! p) { *p 20; } } int main() { test(); while(1); }