【程序员的自我修养—内存模型】

程序的内存布局

kernel space 内核空间:程序无法直接访问
stack

栈:

1. 用于维护函数调用的上下文;

2. 通常有几M的容量

向下生长
dynamic libraries 动态链接库映射区:用于映射装载的动态链接库
向上生长
heap

堆:

1. 用来容纳应用程序动态分配的内存区域;

2. 使用malloc或者new分配内存;

3. 一般比栈大,几十到几百M的容量

read/wirtes sections(.data/.bss)
readonly sections(.init/.roadata/.text) 可执行文件映像
reserved

保留区:

1. 对内存中收到保护而禁止访问的内存区域的总称;

2. 如NULL无法访问,C语言中通常设置为0

问题:程序中出现的段错误和非法操作是怎么回事?

  1. 指针初始化为NULL,没有对指针重新赋值就直接访问;
  2. 没有初始化指针,是一个随机数,没有映射到实际的物理内存上,访问也是非法的;

栈与调用惯例

todo

堆与内存管理

背景:

  • 无法将数据传递到函数外部:因为栈上数据返回时候内存会被释放
  • 全局变量没办法动态产生:只在编译的时候确定,不够灵活

malloc实现:

  • 像操作系统申请一块堆空间,由程序自己管理这块空间(程序的运行库管理)
  • 运行库相当于“批发”了一块空间,然后“零售”给程序,“零售”的办法就是堆的分配算法

堆申请内存方式,执行两个系统调用:

  • int brk(void* end_data_segment)
    • 从数据段结束地址向高地址移动,扩大的部分被用来作为堆空间
  • void *mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset)
    • 向操作系统申请一段虚拟空间(可以映射到某个文件)
    • 当不映射到具体的文件时,这块空间被称为匿名空间,可以拿来作为堆空间
      • 申请的空间起始地址和大小必须是系统页的整数倍
  • glibc的malloc空间请求:
    • 小于128KB的请求,会在现有的堆空间分配一块内存并返回
    • 大于128KB的请求,会使用mmap分配一块匿名空间,然后在匿名空间分配内存

堆分配算法:

  1. 空闲链表法
  2. 位图法
  3. 对象池

你可能感兴趣的:(算法,c++)