一.内存模型
c语言程序在运行时内存分为5个区域(在有些操作系统下分为内存四区),其中初始化数据区、未初始化数据区、代码区在编译时由编译器分配空间,堆区和栈区在程序运行时由系统分配空间。
二.栈
栈主要存放局部变量,函数内存声明的变量都存放在栈内。
int main()
{
int a;
char b;
char arr[100]; //整型、字符型、字符串变量都存放在栈内
}
栈的分配由系统自动管理,不需要程序员干预。
栈会溢出,因为栈空间是有限的,如果在函数中无线分配栈内存会被消耗完
int main
{
int arr[1000000000] = {0};
arr[1000000000 - 1] = 1;
return 0;
}
//error :Segmentation fault (core dumped)
三.堆
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用 malloc 等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用 free 等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
- 堆是总量很大的内存块,需要手动申请或释放内存,其生存周期在malloc和free之间,在free之后不可以访问,否则会造成无法确定的后果。
- 连续两次申请的堆内存地址可能不连续,但一定是从低地址到高地址分配。
动态分配函数
1.malloc
头文件 #include <stdlib.h>
功能 | 在内存的动态区分配一块size字节大小的连续区域,存放指定的类型。malloc会返回void *指针,使用时必须做相应的强制类型转换,分配的空间内容不确定,一般用memset初始化。 |
原形 | void *malloc(unsigned int size) |
参数 | size:申请空间大小 |
返回值 | 成功返回分配空间起始地址,失败返回NULL; |
- malloc()申请的内存在使用完毕之后应该调用free()释放。释放之后这段内存当前进程就不能使用了,可能会被系统分配给其他进程。
- 使用malloc()要保存开辟空间的首地址,在调用free()之前指向这块内存的指针p一定不能丢,也就是不能指向其他地址,否则这块分配的内存在整个程序执行过程中再也找不到了,会造成内存泄露。
- 由于不确定开辟空间类型,malloc()返回值类型为void *,在使用时根据实际情况对其进行强制类型转换。
- 在调用后要判断是否分配成功,及返回值不为NULL。
2.calloc
3.realloc
4.free
头文件 #include <stdlib.h>
功能 | 释放ptr指向的内存 |
原形 | void *free(*void *ptr) |
参数 | ptr:开辟后使用完毕的空间首地址 |
返回值 | 无 |