c语言笔记4-内存管理
1. malloc和free
malloc所分配的是一块连续的内存,以字节为单位,并且不带任何的类型信息
free用于将动态内存归还系统
void* malloc(size_t size);
void free(void* pointer);
注意:
• malloc实际分配的内存可能会比请求的稍微多一点,但是不能依赖于编译器的这个行为
•当请求的动态内存无法满足时malloc返回NULL
•当free的参数为NULL时,函数直接返回
2. calloc和realloc
void* calloc(size_t num, size_t size);
void* realloc(void* pointer, size_tnew_size);
calloc的参数代表所返回内存的类型信息并将返回的内存初始化为0
realloc用于修改一个原先已经分配的内存块大小
在使用realloc之后应该使用其返回值
当pointer的第一个参数为NULL时,等价于malloc
对比:
malloc单纯的从系统中申请固定字节大小的内存
calloc能以类型大小为单位申请内存并初始化为0
realloc用于重置内存大小
3. 栈 在程序中用于维护函数调用上下文,没有栈就没有函数,没有局部变量
栈保存了一个函数调用所需的维护信息
函数参数,函数返回地址
局部变量
函数调用上下文
4. 堆 :
为什么有了栈还需要堆?
栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组
堆是程序中一块巨大的内存空间,可由程序自由使用
堆中被程序申请使用的内存在程序主动释放前将一直有效
5. 静态存储区:
随着程序的运行而分配空间,直到程序运行结束
在程序的编译期静态存储区的大小就已经确定
程序的静态存储区主要用于保存程序中的全局变量和静态变量
与栈和堆不同,静态存储区的信息最终会保存到可执行程序中
6.栈、堆、静态存储区对比:
栈区主要用于函数调用的使用
堆区主要是用于内存的动态申请和归还
静态存储区用于保存全局变量和静态变量
7. 各个段的作用
堆栈段在程序运行后才正式存在,是程序运行的基础
.bss段存放的是未初始化的全局变量和静态变量
.text段存放的是程序中的可执行代码
.data段保存的是那些已经初始化了的全局变量和静态变量
.rodata段存放程序中的常量值,如字符串常量
8. 程序术语对应关系
静态存储区通常指程序中的.bss和.data段
只读区通常指程序中的.rodata段
局部变量所占空间为栈上空间
动态空间为堆中的空间
程序可执行代码存放于.text段
9. 野指针:通常是因为指针变量中保存的值不是一个合法的内存地址而造成的
野指针不是NULL指针,是指向不可用内存的指针
NULL指针不容易用错,因为if语句很好判断一个指针是不是NULL
C语言中没有任何手段可以判断一个指针是否为野指针
野指针由来:
局部指针变量没有被初始化
使用已经释放过后的指针
指针所指向的变量在指针之前被销毁
10.易错点:
①非法内存操作:
结构体成员指针未初始化
没有为结构体指针分配足够的内存
②内存分配成功,但并未初始化
③内存越界:数组越界
④内存泄露
⑤多次指针释放
⑥使用已释放的指针
11.防止出错应遵循的规则:
①用malloc申请了内存之后,应该立即检查指针值是否为NULL,防止使用值为NULL的指针
例:
②牢记数组的长度,防止数组越界操作,考虑使用柔性数组
例:柔性数组的使用
③动态申请操作必须和释放操作匹配,防止内存泄露和多次释放
一般来说,在哪里申请就在哪里释放
如必须要在其他函数里释放,可多加一个参数判断是否在里面释放,如下:
voidf(int* p,int size,int tofree)
{
……
If(tofree)
{
free(p);
}
}
int main()
{
int* p = (int*)malloc(5*sizeof(int));
……
f(p,5,0);
free(p);
return 0;
}
④free指针之后必须立即赋值为NULL
例: