动态内存函数
文章目录
了解内存管理的基本知识
栈区 | 堆区 | 静态区(数据段) |
---|---|---|
局部变量 | 动态内存开辟的地方 | 全局变量 静态变量 |
函数形参 | malloc calloc realloc free |
static修饰的函数或者变量 |
C/C++程序内存分配的几个区域:
栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结
束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是
分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返
回地址等。堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分
配方式类似于链表。数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。
代码段:存放函数体(类成员函数和全局函数)的二进制代码。
malloc
函数
作用:就是在堆上开辟空间
头文件:
<stdlib.h>
格式:
void* malloc (size_t size);
size
是用户设置的大小,单位是字节
需要注意的是,函数的返回值有两种情况:
- 内存开辟成功,返回那个空间的首地址
- 内存开辟失败,返回空指针
NULL
因为会返回空指针,假如这个指针是正在使用的指针,可能会导致数据丢失!!!所以都是先创建临时指针去申请内存,再传地址给正在使用的指针因此一般使用动态内存函数都要有一个判断的过程,方式如下:
int* ptr = (int*)malloc(20 * sizeof(int));//ptr是一个临时指针
if (ptr == NULL)//这是报错提示
{
perror("ptr");
}
int* p = ptr;//p是正在使用的指针
calloc
函数
格式:
void* calloc (size_t num, size_t size);
num
:开辟的数量size
:开辟的类型
功能:
和malloc
一样,都是开辟内存的,返回值,判错方式,头文件都一样
不同点:calloc
函数可以初始化指向空间的内容全为0
int *p = (int*)calloc(10, sizeof(int));
realloc
函数
一种修改申请空间大小的动态内存函数
格式:
void* realloc (void* ptr, size_t size);
ptr
是要调整的内存地址size
调整之后新大小如果
ptr
传的是空指针,用法就和malloc
一样了返回值为调整之后的内存起始位置。
这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
realloc
在调整内存空间存在两种情况:
情况1:
原有空间之后有足够大的空间,就直接原有内存之后直接追加空间,
意思就是原本申请的空间后面地方够大,就给当前的空间再扩大一点,返回的还是之前的地址
情况2:
原有空间之后没有足够大的空间,在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存地址。
意思就是,原来的空间后面没地方了,你又要申请空间,
realloc
就会替你去堆中重新找地方,并把原空间的数据拷贝到新的空间里面,然后free
销毁原来的空间,此时返回这个新的空间的地址
free
函数
一般是和其他的动态内存函数配套使用
头文件
<stdlib.h>
功能:
专门用来释放(回收)在堆上开辟的内存空间
格式:
void free (void* ptr);
ptr
就是要释放的那块空间的首地址,只能是首地址(说明了首地址的重要性)函数的参数部分极易容易出错,一般是p指向的空间不是在堆上开辟的
int a=10;
int *p=&a;
free(p);//error
但是,当p已经被置为空指针时,此时不会有什么影响
常见错误
- 以上函数申请都是无类型的
void*
,都要类型强制转换才可以使用 - 对NULL指针的解引用操作
- 以上函数的申请都可能失败,都要判断一下
- 对动态开辟空间的越界访问
- 申请多少就用多少才行,不能越界
- 对非动态