c语言动态内存规划

当程序被执行的时候要给它两个资源,一个是CPU资源,一个是内存资源,内存分为四个区

从堆区申请内存叫动态内存管理

栈区是函数调用时为函数中的局部变量分配空间,调用完后销毁,由系统管理。

在栈区分配的空间叫做栈帧

可以在这里面重新定义栈的大小,按照字节给的

windows里面的堆区大小为2g,linux的堆区大小为2.7 2.8g接近三g

动态的含义是:在程序运行的过程中

使用动态内存函数时需要用到malloc.h或者stdlib.h

在堆区动态的申请内存主要有三种方式,这三种方式对应三种函数:

1:

size代表字节数,malloc返回无值类型指针

申请成功,返回的是所申请的连续内存空间的首地址

申请失败,返回的是一个空指针

需要指针类型保存它的首地址

它malloc返回的是void型的指针,但是ip是int*,所以需要强制转换为int*

空类型指针,可以被强转为任何类型指针

在对堆区申请的内存进行释放操作的是free函数:

cpp 复制代码
void free(void*p)

只能释放堆区的空间

申请是把某块空间变成引用状态,释放是把引用状态变成未用状态,说明未用。系统会把free的空间打成d,并说明这块空间可以重新引用,打d的目的是为了消除之前的数据,下个使用者再次使用的时候就不能再次使用上个使用者保存的数据,保障安全性

但是ip自身的值没有改变,ip是空悬指针(没有被声明的内存),所以需要把ip赋值为空指针

free是把ip指针所指的位置还给堆区

free之后ip已经跟该空间没有关系了,但是ip仍然指向该空间,仍然可以赋值所以释放完后,一定要把free置为空。更可怕的是。如果ip用完后没有置为空,那它还指向那片空间,如果有is再申请了动态内存如果还含有那片空间,那么无论是给ip赋值还是free(IP)都会对is造成影响,会改变is的值或者is的空间释放,is指向的空间就莫名其妙的失效了

2:colloc函数

colloc函数将申请的内存空间都初始化成0,这是与malloc的主要区别

malloc是将申请的内存空间都初始化成cdcdcd/随机值

在使用动态内存函数的时候,一定要注意判读申请的内存空间是否成功

if(NULL==ip)exit(1);

//exit就是终止函数 后面是1,就是必终止

c语言是类型为王,ip有自己的类型,所以可以对IP解引用

可以通过ip[0]访问申请的空间,所以ip[0]=12就是把申请的内存的第一个空间给成了12

ip[0]=*(ip+0)

如果释放空间后又释放,那么系统会直接给你报错,一旦释放,一定要置为空

一定不要二次释放,因为该空间有可能被别的指针指上并赋值

对于free函数,在free函数里面,如果free的值为空,那它就直接返回了。

如果指针是null,就会直接返回

不为空才释放空间

在用动态内存函数申请空间时,为了防止使用的空间用完了越界,会有上越界和下越界标记,如果上下越界被修改,那就认为程序在运行的过程中出现了越界的问题,free在使用中也会判断是否越界,上越界以上会有头部标记(报头)(头部标记一共占用了28个字节,有4个字节记录了你要申请的字节数),(里面是fdfdfd)占用的字节数为强转的指针大小

报头里面有两个指针,会把你分配给用户的内存块分配到链表里面去

free在运行的时候会读取头部标记,知道释放的字节数

问题1:malloc在申请的时候有说明申请的内存的大小,那为什么free在释放的时候没有传入释放内存的大小?

free在释放的时候,从上越界向上读取完头部标记,就知道自己要释放多少个字节

也就是说,为了达成malloc和free之间的工作方式,给出了一个协议,在malloc申请字节的时候申请的字节比想要申请的字节数大,大了上越界,下越界,和头部信息这么多字节

free在释放的时候,连同上越界,下越界,标记信息都一同释放

free在释放的时候,向上偏移到头部标记,这样就知道自己该释放多少个字节

那我不需要知道字节数,从头部标记一同释放到下越界不就好了?

上下越界会导致用户用数据覆盖,一同释放到下越界会使得用户数据丢失

释放内存时不能部分释放,要么不释放,要么释放完

内存泄漏是什么?

内存泄漏就是,在内存申请完后没有内存释放,或者用动态内存函数获得申请的空间的地址丢失,一旦丢失,意味着你永远也找不到释放的空间的首地址,这也是内存泄漏,所以,一定不要丢失这个地址

为什么空地址就不能给值?

空地址不能解析,不能读或者写,操作系统对0地址有保护,不让对他进行读写,否则操作系统认为出错

3:realloc函数(很重要)

当你发现之前用 malloccalloc 申请的空间太小 (不够用)或者太大 (浪费)时,就需要请出 realloc

全称: Re-allocation(重新分配)。

特点: 可以修改已分配内存块的大小。它会保留原内存中的数据(如果新空间变大,新增的部分是未初始化的随机值)。

原地扩容: 如果原内存块后面有足够的空闲空间,它直接"向后"延伸,地址不变。

异地搬迁: 如果原地空间不足,它会在堆上找一块全新的、足够大的空间,把旧数据复制 过去,释放旧空间,并返回新地址

重要警告:

由于 realloc 可能会改变内存地址,必须用一个新的指针变量接收返回值,或者直接赋值给原指针(但要确保原指针没丢,通常建议先用临时指针接收,判空后再赋值)。

如果传入的 ptrNULLrealloc 的行为等同于 malloc

相关推荐
3108748763 小时前
0005.C/C++学习笔记5
c语言·c++·学习
历程里程碑4 小时前
Linxu14 进程一
linux·c语言·开发语言·数据结构·c++·笔记·算法
JiL 奥4 小时前
Nexus制品归档(c/c++项目)
c语言·c++
梵刹古音4 小时前
【C语言】 字符型变量
c语言·开发语言·嵌入式
wengqidaifeng5 小时前
探索数据结构(二):空间复杂度
c语言·开发语言·数据结构
皮皮哎哟6 小时前
夯实基础:数据结构核心概念与线性表(顺序表&链表)C语言全解析 数据结构篇
c语言·数据结构·顺序表·单向链表·有头链表
划破黑暗的第一缕曙光6 小时前
[数据结构]:4.二叉树_堆
c语言·数据结构·二叉树·
浅念-6 小时前
C语言——双向链表
c语言·数据结构·c++·笔记·学习·算法·链表
wengqidaifeng8 小时前
数据结构---顺序表的奥秘(下)
c语言·数据结构·数据库