栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言1. 动态内存管理+这类读代码题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言1. 动态内存管理+这类读代码题

  1. 为什么存在动态内存分配:
    普通的内存开辟方式开辟空间后,比如数组大小,就不能改变了。要么开大了,要么开小了

动态内存管理的方法:
malloc()、free()、calloc()、realoc()

内存中,空间的使用规则为:

如上图,内存管理使用的函数操作都在堆区上

malloc():返回无类型指针void*
  • 无空间时,给你返回NULL
  • 它返回void* ,但是你可以强制转换
  • 返回后的空间内容,可以随便给值
free():释放
  • malloc()申请后的初始用p接收,但使用过这片空间后,p可能不在初始位置,所以一般使用前先存一个ptr= p,最后free(ptr);
    释放之后,ptr还指向那里,ptr是野指针,给它置空
    所以一般释放+置空:
free(p);
p = NULL;
  • 如果没有free malloc的空间,程序结束,操作系统会自动回收,但是程序一直允许24h,会造成内存泄漏的问题。
// 检查有没有申请好
if(p==NULL)
{
	perror("calloc");
	return 1;
}
calloc():申请数组,初始化为0
申请10个整形数组空间,这里申请的空间会初始化为0
int* p = (int*)calloc(10, sizeof(int));

一般calloc()和malloc()后面检查有没有开辟成功

// 检查有没有申请好
if(p==NULL)
{
	perror("calloc");
	return 1;
}
realloc():动态内存管理更灵活,再开辟
  • 空间不够后,再扩容
int *p = (int*)malloc(40);
// 空间不够后,再扩容
p = realloc(p, 80);

  • 它对p扩容后返回位置:
    当追加发现可能会把别的变量空间占用的话,它会再往后找一片更大空间,并且改变原始p的位置,且拷贝之前数据,且还会把旧的空间free(),返回值是新空间地址。
  • 如果扩容失败,realloc会返回NULL,如果直接用p,把之前的空间p也丢掉了,所以定义新指针去接收返回
int *ptr = (int*)realloc(p, 20);
if(ptr==NULL)
{扩容失败}
注意事项:

malloc和realloc后,都需要对原始指针做NULL判断
 free(p\)时,注意p值是否是p初始位置
对同一块内存多次释放,也出错

且要注意越界访问,如下创建100个字节空间,只能存25个整型,但是这里<=25,越界了

读代码:
程序1

分析:
getMemory()传了str,str是NULL,函数中p是str临时拷贝,p也是NULL,给p申请了空间,函数执行完,p被销毁了,但是申请的空间却没释放,内存泄漏而str还是NULL。
然后main()中strcpy中对NULL解引用,程序崩溃。
问题原因:str本身是NULL,且接收它的是形参,拷贝了NUL。
但是如果你要改变str本身,Get函数中,用二级指针来接收做操作就没问题。
内存泄漏
程序2

Get函数出去后,hello空间就没了,虽然str记着那片地址,但它是野指针,它打印了乱码,野指针可能正常,也可能报错。(返回栈空间地址问题)
有时候野指针访问到值是对的,因为那片旧的区值还未被使用,值为被覆盖,可能得到对的,但程序如果多写几行,函数栈帧会中存新的内容,访问就不一定是之前的值了。
程序4

str不为NULL,会进去strcpy又改值为world,所以错了,野指针,所以free(str)后记得置NULL

程序5

ptr指针没有初始化就使用,野指针问题

======================================
C/C++程序如何开辟空间:
内存中不只是栈区、堆区(动态管理使用)、静态区(数据段),还有内核区,代码段(为了执行代码),用户代码不能读写

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/942866.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号