内存
程序内存的分布
一个程序正在运行的时候,内存有以下分布(五大区):
- 栈区(stack)filo先进后出
- 用来存储函数运行时的临时信息的结构、分配的局部变量、函数的参数、返回值数据、返回地址。这些数据会在函数运行结束后被系统清空。
- 堆区(heap)fifo先进先出
- 一般是由程序分配和释放的,用来存储程序运行时分配的变量的。
- 全局区(静态区static)
- 存储全局变量、静态变量,程序结束后由系统释放。
- 全局区分为:已初始化全局区(.data段)和未初始化全局区(.bss段)
- 常量区(.rodata)只读
- 存储常量字符串,程序结束后由系统进行释放
- 代码区
- 存储函数体(类成员函数、静态函数、全局函数)的二进制代码
注意:栈区和堆区在内存中是对向存储的,如果调用函数、变量等使用太多内存,使用的内存是有可能碰到的,可能会栈溢出。
动态内存分配
不由系统分配内存,而是由程序员分配内存(只有堆区需要)
malloc calloc realloc free
分配内存 分配数组内存 重新分配内存 释放内存
-
malloc
memory allocate: 开辟一个内存空间
void *malloc(size_t size); size: 传入需要分配的内存大小,字节 返回值: 如果分配成功,返回分配空间的首地址 分配失败,返回NULL之所以返回void,是让程序员自己去定义类型
- 分配到:堆区
- 堆区,一旦分配了内存,如果不手动释放,那么该内存会一直存在,直到进程退出
注意:如果在非main的函数中不使用malloc分配的内存,在函数结束时内存就会释放了。所以如果想要让内存保持,就要使用 malloc,malloc分配的内存不用的时候必须要free掉#include <stdio.h> #include <stdlib.h> int main(){ // 以前使用 int a = 100; int *p1 = &a; // 使用:动态内存分配 int *p = NULL; p = (int *)malloc(sizeof(int)); *p = 10; int b = *p; printf("a=%d, b=%d", a, b); free(p); p = NULL; return 0; }
- 分配到:堆区
-
free 释放动态内存分配的内存
int *p = (int *)malloc(sizeof(int)); *p = 100; printf("%d\n", *p); free(p); p = NULL;free只释放堆内存(动态内存分配的内存),不要释放局部变量内存
-
calloc
cell allocate: 用来分配一段空间,用来存储数组
void *calloc(size_t nmemb, size_t size); 作用: 用来分配一段空间,来存储数组 memb: 用来存储数组元素的个数 size: 用来表示数组元素的大小 返回值: 内存分配成功后,返回内存的首地址 内存分配失败,返回NULLcalloc(n, size)) <===> malloc(n*size); // 要想创建一个 int [10] 数组的空间 calloc(10, sizeof(int)); -
realloc
repeat allocate: 重新分配开辟的动态内存大小
void *realloc(void *ptr, size_t size); 作用: 重新分配传入指针指向的空间大小 ptr: 需要重新分配内存的内存首地址 size: 重新分配的内存大小用法:
int *ptr = malloc(10000); int *new_ptr = realloc(ptr, 5000); if(new_ptr){ ptr = new_ptr; }- 改变ptr内存大小后,ptr的原内容不变,无需重新初始化
- 如果ptr==NULL, 那么 realloc(NULL, size) 等价于 malloc(size);
- 如果ptr!=NULL 且 size==0, 那么 realloc(ptr, 0) 等价于 free(ptr);
注意:尽量避免缩小空间,可能会导致数据异常和性能问题。