十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C语言中的动态内存分配

C语言中的动态内存分配 在很多场景数据的大小是在运行时才能确定编译阶段无法确定数据长度或者有大块的数据需要存放但是栈空间不够或者某些参数需要实现跨函数传递或者需要实现可变的数据结构。当面临这些问题时我们往往想到动态分配内存。本文将主要讲在C语言中动态内存分配的4个常用函数以及使用注意事项。一、为什么要用动态内存栈内存存放局部变量大小编译期确认空间很小通常只有几MB函数结束自动销毁堆内存空间大动态分配大小运行时确定但是必须手动管理原因1【主要原因】运行时才知道需要多大内存静态数组写大了浪费内存写小了会溢出动态内存要多少给多少例如用户输入、读取文件、网络接收的数据程序跑起来才知道要多少数据没有办法提前写死。原因2突破栈空间限制栈空间很小一般就1-8MB左右大数据不能放在栈上必须放到堆。原因3内存生命周期不受函数作用域限制栈上的局部变量函数执行完毕就自动释放了不能继续函数外使用动态内存函数结束堆内存依然存在必须手动free才释放eg局部数组函数返回后内存销毁返回指针就是也指针原因4实现可边长数据结构链表、队列、树、哈希表全部离不开动态内存。链表每新增一个节点就要malloc一块内存节点没有动态内存就写不出链表二、四种常用动态内存函数1、四种对比函数参数内存初始化功能mallocmalloc(字节数)不初始化垃圾值分配指定大小堆内存calloccalloc(元素个数每个大小)全部置0分配数组自动清零reallocrealloc(旧指针新总字节)旧数据保留新增部分不初始化修改已分配内存大小扩容缩容freefree指针-释放堆内存malloc和realloc分配的空间生存期是随进程持续性不是随代码块持续性。2、malloc作用分配X字节的堆内存不会初始化内存里面为随机值。分配成功返回内存首地址分配失败返回NULL#includestdio.h#includewindows.h#includemath.hintmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);//在堆上申请10个连续int内存空间int*p(int*)malloc(10*sizeof(int));if(pNULL){printf(动态内存分配失败\n);}else{printf(动态内存分配成功\n);for(inti0;i10;i){printf(%p,存放的内容%lx\n,p[i],p[i]);}}free(p);//用完释放pNULL;// 置空防止野指针return0;}运行结果malloc分配的内存不会自动初始化所有元素默认是随机垃圾值使用前建议手动赋值。3、calloccalloc(num,size)作用分配num个元素每个占用size字节分配完成自动全部初始化为0和malloc的区别calloc会清零malloc不会。//上面的malloc变为callocint*p(int*)calloc(10,sizeof(int));运行结果4、reallocrealloc(ptr,new_size)作用重新修改已分配好的堆内存扩容或缩容ptr:之前得到的指针newsize新的总字节数注意如果后面堆空间足够直接原地扩容返回原来的地址如果后面不够堆找一块全新内存把旧内容复制过去释放旧内存返回新地址失败返回NULL原来旧内容不会释放realloc(ptr,0):长度为0是把原来的空间释放#includestdio.h#includewindows.h#includemath.hintmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);//在堆上申请10个连续int内存空间,并将内存的首地址赋值给整型指针pint*p(int*)calloc(5,sizeof(int));int*tmp(int*)realloc(p,10*sizeof(int));if(pNULL){printf(动态内存分配失败);}else{printf(-----动态内存分配成功-----\n);for(inti0;i5;i){printf(%p,存放的内容%lx\n,p[i],p[i]);}if(tmp!NULL){printf(-----重新分配成功-----\n);ptmp;for(inti0;i10;i){printf(%p,存放的内容%lx\n,p[i],p[i]);}}else{printf(-----重新分配失败-----\n);//分配失败p仍指向旧内存可以继续使用printf(%p\n,p);}}free(p);//用完释放pNULL;// 置空防止野指针return0;}运行结果注意realloc直接用原指针接收返回值失败会导致内存泄漏例子中直接写prealloc(p,newsize);如果失败p被赋值为NULL原内存地址丢失直接内存泄漏。realloc(NULL,n)等价于malloc(n)5、free释放内存作用释放堆内存还给操作系统规则参数必须是malloc、realloc、calloc返回的地址不能传栈变量地址free之后原来的指针变量仍然保存旧地址变为野指针建议手动赋值为NULL不能重复free同一个指针程序会崩溃free(NULL)是安全的什么都不做三、使用注意事项1、实际项目大量使用动态内存malloc、realloc、calloc、free但是不能无脑使用滥用会付出巨大代价内存泄漏忘记free程序越跑内存占用越高长期运行服务直接卡死。野指针free之后继续使用重复free直接崩溃realloc坑点分配失败处理麻烦频繁malloc、free会产生内存碎片长时间运行内存效率下降所以小固定大小缓冲区优先栈数组不要mallocmalloc和free尽量配对谁申请谁释放嵌入式设备内存很小尽量少用动态内存必要时禁止malloc2、垃圾内存/内存泄漏char*pmalloc(10);chara;pa;//p本来指向10字节的动态内存分配的空间现在指向a上述代码没有任何指针会指向那段动态内存分配的空间并且那段空间不会释放变为垃圾内存或说内存泄漏解决办法方案一p指向其他对象之前先释放free(p);pa;方案二p指向其他对象之前给那段空间找一个索引指针char*qp;//后面可以通过q来释放这段空间。pa;
返回列表