基础回顾-7 内存管理

开局一张图,内容全靠编。(开个玩笑,内容当然不是编的)

程序运行之前

程序代码编写完之后,如果要运行程序,我们还需对程序做编译工作。

编译过程:
1、预处理:头文件展开、宏定义展开(替换宏)、条件编译。 
2、编译:检查语法,将预处理后文件编译生成汇编文件。
3、汇编:将汇编文件生成目标文件,即二进制文件。
4、链接:将目标文件链接为可执行程序。
复制代码

可执行程序分为三段,分别为代码段 text 、已初始化数据段 data 和 未初始化数据段 bss 3个部分。
可以将这三段分为两种,一种是 程序指令 段即代码段 text。另一种则是 程序数据 ,包含数据段 data 和 未初始化数据段 bss

* 代码段 text 段: 存放程序代码,编译时确定,只读。
* 数据段 data 段: 存放在编译阶段就能确定的数据,可读可写。
                这个就是常说的 静态存储区,存放 初始化了的的全局变量和静态变量,
                还有常量(这个只读)。
* 未初始化数据 bss 段: 存放已经定义了的,但是没有初始化的全局变量和静态变量。
复制代码

程序运行之后

程序加载到内存前,代码区和数据区的大小就是固定地,程序运行期间不能改变。运行可执行程序时,操作系统加载硬盘到内存,根据可执行程序的信息,分出代码区(text),数据区(data),未初始化的数据区(bss)之外,还额外增加了 栈区堆区

栈区 :由系统进行内存的管理。主要存放函数的参数及局部变量。在函数完成执行,系统自行释放栈区内存,不需要用户管理。静态内存分配,编译时确定大小。是一种连续存储的数据结构,遵守 先进后出 原则。

堆区 :由 coder 手动申请,手动释放的内存区。如果不手动释放,只有等程序结束后由系统回收。容量远远大于栈区,但是速度比栈区慢,用于做动态内存分配,运行时确定大小。位于 bssstack(栈区) 之间。不连续的存储结构,遵守 先进先出 原则。

内存的分配

内存分配方法 void *malloc(size_t __size)

参数类型为 size_t ,其实是 unsigned long 无符号长整型类型。 __size 是需要开辟的内存字节数,比如 malloc(10) ,这是在堆区开辟了十个字节长的空间。

返回值类型是 void * ,这是 泛型指针,可以赋值给任何一种指针类型的变量。
malloc 方法有一定的几率会失败,失败时返回一个 NULL 空指针。

void free(void *) 在使用完了 malloc 分配的堆空间内存之后,要对其进行释放,避免内存泄漏。

内存的分配方向

由最前的面的图可以看出,栈区stack 位于高地址位,堆区位于低地址位。
栈区

void func (void) {
    int a;
    int b;
    printf("a: %p ,b: %p \n",&a,&b);
}
复制代码

在一个函数 func 中定义了两个变量 ab ,函数位于栈区,我们打印两者的地址得到的结果 a: 0x7ffeefbff5bc ,b: 0x7ffeefbff5b8a 的地址比 b 的大,我们也知道代码是一行行从上往下执行的,所以说栈区的内存增长方向,是 从高位向低位增长

堆区

int *p = malloc(4);
int *q = malloc(4);
printf("p: %p ,q: %p \n",p,q);
复制代码

使用 malloc 方法,在堆区申请内存,得到的结果是 p: 0x10052ab50 ,q: 0x10052af70p 的地址比 q 的小,说明堆区内存增长方向,是 从低位向高位增长

转载于:https://juejin.im/post/5d0056035188253d592e02e1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值