网站域名备案后公示南宁做网站比较好的公司
news/
2025/10/3 19:33:59/
文章来源:
网站域名备案后公示,南宁做网站比较好的公司,河北网站开发报价,阿里巴巴官网电脑版目录
1.动态内存分配的原因
2.动态内存函数的介绍
2.1malloc和free函数
2.2calloc函数
2.3realloc函数
3. 常见的动态内存错误
3.1 对NULL指针的解引用操作
3.2 对动态开辟空间的越界访问
3.3 对非动态开辟内存使用free释放
3.4 使用free释放一块动态开辟内存的一部…
目录
1.动态内存分配的原因
2.动态内存函数的介绍
2.1malloc和free函数
2.2calloc函数
2.3realloc函数
3. 常见的动态内存错误
3.1 对NULL指针的解引用操作
3.2 对动态开辟空间的越界访问
3.3 对非动态开辟内存使用free释放
3.4 使用free释放一块动态开辟内存的一部分
3.5 对同一块动态内存多次释放
3.6 动态开辟内存忘记释放内存泄漏
4.动态内存经典笔试题
4.1题目1
4.2 题目2
4.3 题目3
5. C/C程序的内存开辟
6.结语 1.动态内存分配的原因 我们目前知道的申请内存的两种方法 int val 20;//在栈空间上开辟四个字节
char arr[10] {0};//在栈空间上开辟10个字节的连续空间 但是上述申请内存的办法一旦开辟完成内存空间的大小就固定了就像我们的数组超出内存范围就会产生越界的问题没有办法改变内存的大小非常死板固定化不够灵活。我们想要更灵活的使用内存空间当我们觉得少了就补充空间。 总的来说 上述的开辟空间的方式有两个特点 1. 空间开辟大小是固定的。 2. 数组在申明的时候必须指定数组的长度它所需要的内存在编译时分配。 但是对于空间的需求不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道比如主页的通讯录项目只能存储1000个人信息当我们的联系人信息到101个就无法存储了 那数组的编译时开辟空间的方式就不能满足了。 这时候就只能试试动态存开辟了。 注意 固定的内存开辟如我们熟知的两种方式虽然内存使用不自由但是内存管理更为简便。 自由的动态内存分配可能会导致更为复杂的内存管理问题。 2.动态内存函数的介绍
2.1malloc和free函数 C语言提供了动态内存开辟也就是可以申请内存的函数 函数头文件stdlib.h 函数功能 ① 这个函数向内存申请一块连续可用的空间并返回指向这块空间的指针空间的起始地址。 ②如果开辟成功则返回一个指向开辟好空间的指针。 比如我们以前用数组申请40个字节的空间我们会这样来做 int arr[10]; 现在使用malloc可以这样来用 malloc(40) 那么现在我们对这个malloc申请的空间进行访问最好的方式是不是可以当做一个整型来访问那我们将函数的返回值放在一个整型指针中访问一次跳过4个字节但是malloc的返回值是void*需要强制类型转换 int *p malloc(40); ③如果开辟失败则返回一个NULL指针因此malloc的返回值一定要做检查。 int* p (int*)malloc(40);//开辟成功返回指针自己要知道申请的这段空间用于做什么才好确定类型//可能开辟失败做一下判断if (p NULL){peror(malloc);//打印错误原因return 1;}//开辟成功就可以利用p来访问这块空间int i 0;for (i 0; i 10; i){printf(%d\n, *(p i));} 看一下打印结果 这里补充图解 ③返回值的类型是 void* 所以malloc函数并不知道开辟空间的类型具体在使用的时候使用者自己 来决定。 ④如果参数 size 为0malloc的行为是标准是未定义的取决于编译器 malloc0 建议不这么写。 ⑤malloc只负责申请或者开辟空间当空间用完不是吧空间用尽的意思是申请内存来做事这个动作结束不会主动还给操作系统除非程序结束。当程序不退出动态申请的内存不会主动释放。所以当我们用完申请的空间后就要使用free空间来释放我们申请的空间将他还给操作系统不然就会出现很大的内存问题。 举例来说 我们看这段代码 while1
{
int* p malloc(40);
}这就是一个病毒程序只要我们一启动程序就一直向我们的内存申请空间原先申请的又不释放最终会导致内存卡死除非关机如果写入开机程序就会循环往复。所以申请空间后需要释放我们介绍free内存释放函数。 C语言提供了free函数用于做动态内存的释放和回收 函数头文件stdlib.h 函数功能 ①如果参数 ptr 指向的空间不是动态开辟的那free函数的行为是未定义的。 就是说我们的free只能释放我们的动态申请的内存空间如果 int a 0;
int * ptr a;
free(ptr);//错误写法 这种用法就是C语言标准未定义的是错误的。 ②如果参数 ptr 是NULL指针则函数什么事都不做。 ③当空间被释放后原先指向这片空间的指针需要我们手动将其置空变为空指针因为原先的空间被释放了但是指针里面还保存着我们原先的地址当不慎使用这个指针的时候这个时候我们的指针就会变成野指针会造成程序出现问题所以需要手动置空。 int main()
{//代码1int num 0;scanf(%d, num);int arr[num] {0};//代码2int* ptr NULL;ptr (int*)malloc(num*sizeof(int));if(NULL ! ptr)//判断ptr指针是否为空{int i 0;for(i0; inum; i){*(ptri) 0}}free(ptr);//释放ptr所指向的动态内存ptr NULL;//手动置空return 0;
} 补充free函数可能运作的机制 当我们的malloc去开辟空间的时候比如我们需要开辟40个字节的空间但是当我们的函数在执行的时候可能会稍微开辟大一点的空间 2.2calloc函数 C语言还提供了一个函数叫 calloc calloc 函数也用来动态内存分配。原型如下 函数头文件stdlib.h 函数功能 ①函数的功能是为 num 个大小为 size 的元素开辟一块空间并且把空间的每个字节初始化为0。 ②与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 ③也有可能开辟失败所以需要和malloc一样做判断 例子使用 int main()
{int* p (int*)calloc(10, sizeof(int));if (p NULL){perror(calloc);return 1;}//开辟成功打印int i 0;for (i 0; i 10; i){printf(%d, p[i]);}//释放free(p);p NULL;return 0;
} 将每个字节初始化为0. 我们看一下开辟失败的情况 int main()
{int* p (int*)calloc(INT_MAX*2, sizeof(int));if (p NULL){perror(calloc);return 1;}//开辟成功打印int i 0;for (i 0; i 10; i){printf(%d, p[i]);}//释放free(p);p NULL;return 0;
} 2.3realloc函数 realloc函数的出现让动态内存管理更加灵活。 有时会我们发现过去申请的空间太小了有时候我们又会觉得申请的空间过大了那为了合理的时 候内存我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小 的调整。 函数头文件stdlib.hptr 是要调整的内存地址(被调整空间的起始地址如果这里传入一个空指针和malloc函数功能一样size 调整之后新大小这里不是在后面补充是包括原先已经申请好的大小比如原先申请了10个空间不够不能说size传10变成20个空间而是传20,变成一个20大小的空间。返回值为调整之后的内存起始位置。所以当我们用一个指针来接收返回值的时候这个指针可能指向原先malloc开辟的空间的起始位置也有可能指向一块新空间这和realloc函数功能相关下面两种情况增容失败会返回空指针。 补充 int * p (int*)malloc(40);
if(p NULL)
{
perror(malloc);
return 1;
}
//增加空间
p realloc(p,80); 注意这种写法不严谨因为我们的realloc函数有可能增容失败比如后续实在没有空间了就会增容失败失败返回空指针赋值给P,就导致P原先维护的40个字节的空间也找不到了内存空间既用不上也找不到就会造成内存泄漏。正确的做法应该是重新使用一个指针来接收。 这个函数调整原内存空间大小的基础上还会将原来内存中的数据移动到 新 的空间。 realloc在调整内存空间的是存在两种情况 情况1原有空间之后有足够大的空间直接在后面开辟空间后返回原始空间的地址。 情况2当申请空间的后续空间的内存被别的占用无法扩展原有空间之后没有足够多的空间时扩展的方法是在堆空间上另找一个合适大小 的连续空间来使用。这样函数返回的是一个新的内存地址。 四步 1.首先会开辟新的空间 2.会将旧空间中的数据看拷贝到新空间 3.释放旧的空间realloc函数会做 4.返回新的空间的起始地址 我们来看一下这个函数的正确使用 int main()
{int* p (int*)malloc(40);if (p NULL){perror(malloc);return 1;}//开辟成功打印int i 0;for (i 0; i 10; i){p[i] i 1;}//增加一些空间int * ptr (int*)realloc(p, 80);//判断一下if (ptr ! NULL){p ptr;ptr NULL;}else{perror(realoc);return 1;}for (i 0; i 20; i){printf(%d\n, p[i]);}//释放free(p);p NULL;return 0;
} 3. 常见的动态内存错误
3.1 对NULL指针的解引用操作
void test()
{int *p (int *)malloc(INT_MAX/4);*p 20;//如果p的值是NULL就会有问题free(p);
} 如果malloc开辟空间失败返回空指针就会出问题应该是开辟伴随着判断。 3.2 对动态开辟空间的越界访问 我们申请的空间也是有大小的不可以申请40字节空间做需要80空间的事。 3.3 对非动态开辟内存使用free释放 我们的free只能释放我们的动态申请的内存空间 3.4 使用free释放一块动态开辟内存的一部分 注意对比 p[i] i1; p[i] *(pi)//p指向的位置没变 3.5 对同一块动态内存多次释放 3.6 动态开辟内存忘记释放内存泄漏 void test()
{int *p (int *)malloc(100);if(NULL ! p){*p 20;}
}
int main()
{test();while(1);
}这是一段极端代码我们的程序运行起来由于p是局部变量出了函数就销毁了那开辟的空间虽然在我却没有地址找到了想释放都释放不了用不上也找不到就内存泄漏了。 每天跑一跑内存少一少内存耗干重启又开始耗这就是一个服务器BUG代码。 最好的理解例子 梁朝伟的无间道 当卧底的一直和唯一的警察单线联系当这个警察死掉了就没人知道你的真实身份了。 4.动态内存经典笔试题
4.1题目1 void GetMemory(char *p)
{p (char *)malloc(100);
}
void Test(void)
{char *str NULL;GetMemory(str);strcpy(str, hello world);printf(str);
}问运行会有什么样的后果 分析 代码问题 ①对空指针进行解引用导致程序崩溃 ②动态申请的空间没有释放且无法释放导致内存泄漏。 4.2 题目2 char *GetMemory(void)
{char p[] hello world;return p;
}
void Test(void)
{char *str NULL;str GetMemory();printf(str);
} 问运行以上代码会有什么样的结果 分析 结果是非法访问 这是典型的返回栈空间地址的问题 当我们使用static修饰延长这个空间的生命周期就可以了 4.3 题目3 请问运行Test 函数会有什么样的结果 void GetMemory(char **p, int num)
{*p (char *)malloc(num);
}
void Test(void)
{char *str NULL;GetMemory(str, 100);strcpy(str, hello);printf(str);
} 问题在于最后申请弟弟空间没有释放 freestr
str NULL; 5. C/C程序的内存开辟 C/C程序内存分配的几个区域 1. 栈区stack在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结 束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是 分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返 回地址等。 2. 堆区heap一般由程序员分配释放 若程序员不释放程序结束时可能由OS回收 。分 配方式类似于链表。 3. 数据段静态区static存放全局变量、静态数据。程序结束后由系统释放。 4. 代码段存放函数体类成员函数和全局函数的二进制代码。 有了这幅图我们就可以更好的理解在《C语言初识》中讲的static关键字修饰局部变量的例子了。 实际上普通的局部变量是在栈区分配空间的栈区的特点是在上面创建的变量出了作用域就销毁。 但是被static修饰的变量存放在数据段静态区数据段的特点是在上面创建的变量直到程序 结束才销毁 所以生命周期变长。 6.结语 以上就是本期的所有内容知识含量蛮多大家可以配合解释和原码运行理解。创作不易大家如果觉得还可以的话欢迎大家三连有问题的地方欢迎大家指正一起交流学习一起成长我是Nicn正在c方向前行的奋斗者感谢大家的关注与喜欢。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/926240.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!