开辟堆区空间
切记代码一定要记得释放
程序代码区
常量区存放常量。程序结束时由OS回收。
全局区(静态区)存放全局变量和静态变量。初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束时由OS回收。
堆区存放的变量(用new,malloc,calloc,realloc等分配内存函数得到的变量)由程序员分配释放。
栈区存放的变量(局部变量、函数参数等)由编译器自动分配释放。
int*p=(int*)melloc(sizeof(int))
用melloc开辟的空间
失败会返回一个NULL指针因此开辟完记得检查一下空间
成功会返回一个指针地址,这个指针是void*类型的,所以看需求给指针类型
不能开辟大小为0的地址
提供free函数用来动态释放内存空间
释放完指针变量还是存在的,记得p=NULL
如果释放了一个空指针则不做处理
不能使用free对同一块内存空间重复释放
free释放的是内存空间,而不是指针。
——释放,指针指向的内存空间可以被其他变量所占用,
但被占用前,内存空间中的内容仍然存在。但是无法判定是否被占用
如果非法使用动态内存非常危险,后果无法预料
动态内存是开辟在堆上的。栈里使用的内存计算机会自动回收开辟
calloc(10,sizeof(int))返回一个指针并初始化这篇空间并且把空间每个字节初始化为0
relloc内存拓展,调整动态开辟内存的大小
relloc(p,10*sizeof(int))拓展p指向的内存
1、如果开辟的空间大小小于p指向的空间后边的内存大小则直接开辟
2、如果小于就会开辟出一块新的空间,拷贝原来数据并且释放掉原来的空间
再次释放空间时只需要释放新开辟的空间就好了
内存泄漏
若动态开辟的内存一直没得到释放就可能会造成内存泄漏
这段代码传的str是值,是地址但是地址作为值传过去
void get(char*p) { p=(char*)(malloc(100)); } int main() { char str=NULL; get(str); }
内核空间
栈(向下增长)主要存运行时函数参数、局部变量、返回地址、返回数据 操作系统回收
内存映射段
堆(向上增长)程序若不释放可能有操作系统回收
数据段(全局数据、静态数据)操作系统回收
代码段(可执行代码?只读代码)例如char arr=“hello”;为常量字符串
柔性数组
include<string.h>
#include<errno.h>
struct st_type
{
int i;//4字节
int a[0];//柔性数组成员,也可以写int a[];
};
int main()
{
//假设我现在需要a里有10个元素
struct st_type*ps=(struct st_type*)malloc(sizeof(struct st_type) + 10 * sizeof(int));
if (ps == NULL)//由于空间可能不够开辟导致malloc开辟失败,开辟失败会返回空指针
{
printf("%s\n", strerror(errno));
return -1;//程序出问题后,跳出程序
}
//开辟成功
int j = 0;
for (j = 0;j < 10;j++)
{
ps->a[j] = j;
}
for (j = 0;j < 10;j++)
{
printf("%d ", ps->a[j]);//打印0-9
}
printf("\n");
//如果想继续用柔性数组a进行打印
//比如现在a里只有10个元素,我用完10个了,我还要继续来10个,用realloc追加
struct st_type*ptr=realloc(ps, sizeof(struct st_type) + 20 * sizeof(int));//ps:realloc第二个参数是调整后的整体大小
if (ptr == NULL)
{
printf("扩容失败\n");
return -1;
}
else
{
ps = ptr;
}
//扩容成功
int k = 0;
for (k = 10;k < 20;k++)
{
ps->a[k] = k;
}
for (j = 0;j < 20;j++)
{
printf("%d ", ps->a[j]);//打印0-19
}
//释放空间
free(ps);
ps = NULL;
return 0;
}
NULL; return 0; }