linux c内存分配方式以及动态内存分配
从静态存储区分配(由系统控制)
内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,staic变量
在栈上分配(由系统控制)
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。效率很高,凡事分配的内存容量有限
在堆上分配,亦称动态内存分配(由自己控制)
程序在运行时用malloc
等函数申请任意多少的内存,程序员自己负责在何时用free
释放内存。动态内存的生命周期有我们自己决定,使用非常灵活,但问题也最多
malloc函数
void *malloc(size_t size);
- 使用:需要包含
malloc.h
头文件 - 功能:允许从空闲内存池中分配连续内存但不初始化
- 参数:
size
参数是一个所需字节数 - 返回:若分配成功则返回一个指向该内存块的指针,在使用时可根据需要做强制类型转换,否则返回
NULL
指针
calloc函数
void *calloc(size_t num_elements,size_t element_size);
- 使用:需要包含
malloc.h
头文件 - 功能:功能与
malloc
函数相同,但作初始化 - 参数:
num_elements
是所需元素的数量,element_size
是每个元素的字节数 - 返回:与
malloc
相同
realloc含糊
void *realloc(void *ptr,size_t new_size)
- 使用:需要包含
malloc.h
头文件 - 功能:在指针
ptr
指向的内存基础上扩大或缩小内存 - 参数:
ptr
是指向先前通过malloc
、calloc
或realloc
函数后分配的内存块的指针,new_size
是内存块的新尺寸,可能大于或小于原有内存尺寸 - 返回:若能调整内存大小则返回指向调整后内存的指针,否则返回
NULL
realloc函数的使用注意点
- 当扩展内存时,不会对添加的内存块的字节进行初始化
- 弱不能调整内存则返回
NULL
,但原有内存中的数据不会发生改变 - 若第一个参数为
NULL
那么功能等同于malloc
函数,若第二个参数为0,那么会释放调用内存块。 - 在缩小或扩大内存时一般不会对其进行移动,若无法扩大内存块(内存块后面的字节已经用于其他木的),那么可能会在别处分配心的内存块,然后把旧块的数据复制到新块中,并将旧块删除释放内存
free函数
void free(void *ptr);
- 功能:释放由指针
ptr
指向的动态内存分配的内存块
free函数注意点
- 如果
ptr
是NULL
指针,那么free
对ptr
无论操作多少次都不会出问题 - 如果
ptr
不是NULL
指针,那么free
对ptr
连续操作两次就会导致程序停止运行
示例
// stdlib会包含malloc
#include <stdlib.h>
#include <stdio.h>
void print_arr(int *p,int length);
int main(void)
{
size_t length = 0;
scanf("%d",&length);
if(length > 0)
{
// 使用malloc分配内存
//int *p = (int*)malloc(length);
// 使用calloc分配内存
int *p = (int*)calloc(sizeof(int),length);
p[0] = 8;
print_arr(p,length);
// 使用 realloc修改申请的内存空间的大小
p = realloc(p,length + 2);
print_arr(p,length + 2);
free(p);
// 注意虽然释放了申请的内存,但是这个注意要清空下指针
p = NULL;
}
return 0;
}
void print_arr(int *p,int length)
{
for(int i = 0;i < length;i++)
{
printf("p[%d] = %d;\n",i,p[i]);
}
}