news 2026/5/3 18:33:25

动态内存 stdlib.h 库函数的简单介绍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动态内存 stdlib.h 库函数的简单介绍

目录

动态内存的申请空间位置

malloc calloc realloc 申请空间

malloc

calloc

realloc

free 释放空间

常见的动态内存的错误

错误1

错误2

错误3

错误4

错误5

错误6


动态内存的申请空间位置

计算器内存空间分布主要分为栈区、堆区、静态区(当然还有其他取于)

主函数内声明的变量:默认情况下,函数内声明的非静态局部变量(如int a;)存储在栈区,而非静态区。只有显式使用static关键字的局部变量(如static int b;)才会存储在静态区。

动态内存空间申请出来的变量是在内存的堆区里。

动态内存空间具有灵活性和动态分配。

灵活性是因为可以随意控制想要的大小

#include <stdio.h> int main(){ int i=0; scanf("%d",&i); int a[i];//error return 0; }

象征着代码就是没办法控制想要打开的大小的,而动态内存就可以做到这些事情。


malloc calloc realloc 申请空间

  • malloc

malloc 函数 ,是申请空间里最常见,也是最基础的函数

void* malloc (size_t size);
  • 参数size为需要分配的字节数。
  • 返回值是一个void*类型的指针,指向分配的内存起始地址;若分配失败则返回NULL。当malloc 在申请空间太大时,或者电脑内存不够时才会申请空间失败。

以为malloc 是void* 的返回形式,所以我们在使用的时候都需要进行一个强制类型转换操作。

int* a=(int*)malloc(sizeof(int));//单个变量申请操作 if(a==NULL){ perror("malloc"); return 1; } //判断空间是否申请成功 int i=0; scanf("%d",&i); int* arr=(int*)malloc(sizeof(int)*i);//可控制数组长度的多个变量申请操作 if(arr==NULL){ perror("malloc"); return 1; } //判断空间是否申请成功

  • calloc

void *calloc(size_t num, size_t size);
  • 参数
    • num:需要分配的元素数量。
    • size:每个元素的大小(字节数)。
  • 返回值
    • 成功时返回指向分配内存的指针。
    • 失败时返回NULL
int i=0; scanf("%d",&i); int* arr=(int*)calloc(i,sizeof(int));//可控制数组长度的多个变量申请操作 if(arr==NULL){ perror("malloc"); return 1; } //判断空间是否申请成功
int i=0; scanf("%d",&i); int* arr=(int*)malloc(sizeof(int)*i);//可控制数组长度的多个变量申请操作 if(arr==NULL){ perror("malloc"); return 1; } //判断空间是否申请成功

calloc 也是生成动态内存,但与 malloc 有点不一样

void* malloc (size_t size); void* calloc(size_t num,size_t size); int* p = (int*)malloc(i * sizeof(int)); int* p = (int*)calloc(i , sizeof(int));


两个功能是一样的
malloc生成出来的值是随机值calloc生成出来的值会经行一个初始化0的操作

性能:由于calloc会初始化内存,其性能可能略低于malloc,但安全性更高。


  • realloc

realloc 的功能就是当你申请的空间太小或者太大时的时候

realloc 进行对与内存大小的调整

void* realloc (void* ptr ,size_t size );
  • 参数:

ptr 是要调整的内存的地址
size 是调整后的新大小,单位字节

  • 返回值

    • 成功时返回指向分配内存的指针。
    • 失败时返回NULL
int* ptr =(int*)malloc(sizeof(int)); if(ptr==NULL){ perror("malloc"); return 1; } realloc(ptr,sizeof(int)*5); if(ptr==NULL){ perror("realloc"); return 1; } //这种写法会容易出现问题 /* 当realloc申请空间失败时,容易把之前的空间一起变成空指针NULL */

正确做法

#include <stdlib.h> int main(){ int* arr1=(int*)malloc(sizeof(int)*5);//内存申请空间 if(arr1==NULL){ perror("malloc"); return 1; } for(int i=1;i<=5;i++) arr1[i]=i;//赋值 int* arr2=realloc(arr1,sizeof(int)*10);//设置arr2 扩充文件内存 if(arr1==NULL){ perror("realloc"); return 1; } arr1=arr2; for(int i=6;i<=10;i++) arr1[i]=i;//赋值 free(arr1);//释放空间 arr1=NULL;//防止野指针 return 0; }

realloc在调整内存空间的时候会出现一下两种情况

情况1: ptr

20bit尚未分配位置

内存空间扩展充沛的情况:

当是情况1的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化。

情况2: ptr

20bit尚未分配位置

内存空间扩展不充沛的情况:

当是情况2的时候,原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间
来使用。这样函数返回的是一个新的内存地址。


free 释放空间

当我们该内存不许要使用的时后 ,就可以通过内存空间释放来,减少计算机内存负担,避免空间的浪费。

free(ptr); ptr=NULL;

如果没有及时释放空间,空间就一直被占用,着未正确释放内存会导致内存泄漏,长期运行的程序可能因内存耗尽而崩溃,直到程序结束。

所以内存空间释放是横有必要的存在。


常见的动态内存的错误

错误1

#include <stdio.h> char* get_mory(void){ char p[]="hello world"; return p; } void test(void){ char* str=NULL; str=get_mory(); printf(str); } int main(){ test(); return 0; }

char p[]="hello world"是一个局部数组,存储在栈上。

get_mory函数返回时,栈帧被释放,p的内存不再有效。返回的指针p成为悬挂指针,访问它会导致未定义行为。

相当于get_mory返回指针后,因为“hello world”是在栈区上的数组,却又因为是局部变量,就会导致出了函数后就会销毁,已经没有hello world 这个数据了。

正确做法:

char* get_mory(void){ static char p[]="hello world";//static 修饰的数组存在于内存的静态区 return p; }

利用static 让hello world 保存在内存的静态区,hello world 进行输出。


错误2

#include <stdio.h> #include <stdlib.h> void GetMemory(char*p) { p = (char*)malloc(100); } void Test(void) { char* str = NULL; GetMemory(&str); strcpy(str, "hello world"); printf(str); } int main() { Test(); return 0; }

1.程序崩溃
原因是:
str传递给GetMemory函数的时候,采用的值传递
形参变量p其实是str的一份拷贝
当我们把malloc申请的空间的起始地址存放在p中时
不会修改str,str依然为NULL
所以当GetMemory函数返回后,再去调用strcpy函数需要
将“hello world”拷贝到str指向的空间时,程序崩溃。
2.因为malloc申请的空间没有free释放,存在内存泄露

正确做法:

#include <stdio.h> #include <stdlib.h> void GetMemory(char** p) { *p = (char*)malloc(100); printf("%c", **p); } void Test(void) { char* str = NULL; GetMemory(&str); //经过这了从单个变量转变成数组 strcpy(str, "hello world"); printf(str); free(str); str = NULL; } int main() { Test(); return 0; }

错误3

#include <stdio.h> #include <stdlib.h> void test(){ char* str=(char*)malloc(100); strcpy(str,"hello"); free(str); if(str!=NULL){ strcpy(str,"world"); printf(str); } } int main(){ test(); return 0; }

错误操作:

1,野指针问题,会非法访问内存。程序崩溃。

2,什么都打印不出来。

所以free 内存被释放之后,但是str还是地址还真在的,所以为了防止无意识的使用到已经free 释放可空间的时候还是要经行str = NULL,操作


错误4

#include <stdlib.h> int main(){ int* ptr=(int*) malloc(sizeof(int)*10); if(ptr==NULL){ perror("malloc"); return 1; } for(int i=0;i<10;i++){ *ptr=i; ptr++; } free(ptr); ptr=NULL; return 0; }

错误操作:

free释放空间,一定要在要在内存空间从起始位置。

*ptr=i;ptr++;

该成ptr[i]=i;


错误5

int test(){ int* ptr=(int*) malloc(sizeof(int)*10); if(ptr==NULL){ perror("malloc"); return 1; } //.... free(ptr); return p; } int main(){ int *ptr=test(); free(ptr); ptr=NULL; return 0; }

错误操作:

内存的二次释放也是不行的。


错误6

int main(){ int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = arr; //.. free(p); p = NULL; return 0; }

错误操作:

对非malloc的动态内存空间经行释放空间操作

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 18:33:20

鼠标连点器:游戏玩家的得力助手

在玩某些游戏的时候&#xff0c;我们经常需要反复点击鼠标&#xff0c;时间长了手指会很酸痛。 而且有些场景需要非常快速的连点&#xff0c;手动很难达到理想的速度。 这时候鼠标连点器就派上用场了&#xff0c;能帮我们完成这些重复性的点击工作。 今天我们要介绍的这款鼠标连…

作者头像 李华
网站建设 2026/5/3 18:33:19

软件评测师基础知识专项刷题:网络安全技术(一)

前言软考软件评测师备考之路&#xff0c;基础刷题必不可少。本文围绕【网络安全技术】模块整理经典习题 核心考点梳理&#xff0c;系列内容长期连载更新&#xff0c;慢慢积累、逐个突破&#xff0c;轻松夯实应试功底。考点防火墙防火墙是在内部网络和外部因特网之间增加的一道…

作者头像 李华
网站建设 2026/5/3 18:17:27

通过Taotoken用量看板清晰掌握团队API成本与模型消耗

通过Taotoken用量看板清晰掌握团队API成本与模型消耗 1. 用量看板的核心功能 Taotoken用量看板为团队管理者提供了多维度的API调用数据可视化能力。登录控制台后&#xff0c;在「用量分析」模块可查看实时和历史token消耗情况。系统默认展示最近7天的数据&#xff0c;支持按小…

作者头像 李华
网站建设 2026/5/3 18:14:11

FontForge终极指南:免费开源字体编辑器的完整实战教程

FontForge终极指南&#xff1a;免费开源字体编辑器的完整实战教程 【免费下载链接】fontforge Free (libre) font editor for Windows, Mac OS X and GNULinux 项目地址: https://gitcode.com/gh_mirrors/fo/fontforge 还在为字体设计软件的高昂费用而烦恼吗&#xff1f…

作者头像 李华