【问题标题】:How is heap usually implemented? [duplicate]堆通常是如何实现的? [复制]
【发布时间】:2011-05-13 00:59:02
【问题描述】:

可能重复:
How is heap and stack memories managed, implemented, allocated?

嗨, 我的问题是关于堆,而不是数据结构,而是用于动态内存分配的内存区域。

假设我们正在用 C(或者可能是 C++)编写一个程序,并且在其代码深处的某个地方调用了 malloc()(或者在 C++ 的情况下调用了 operator new)。现在分配的内存的位置是什么?编译器(链接器?)是否添加了用作堆的数据段?该段的大小是如何确定的?如果我们尝试分配一块大于整个“堆段”的内存会发生什么?堆会扩大吗?如果是,怎么做?

【问题讨论】:

    标签: c++ c memory heap-memory low-level


    【解决方案1】:

    旧的 unix 实现使用机制 sbrk()--系统请求移动最后一个数据段边界。分配内存时,tuntime 库调用系统将数据边界向上移动,并使用新的内存。

    新的操作系统使用虚拟内存,因此 malloc 会在必要时向系统请求新的空闲 VM 页面。

    独立应用程序(在裸硬件、微控制器等上运行)都分配了内存。库知道所有内存,因为链接描述文件定义了动态区域的符号。例如。 freemembotfreememtop 之类的东西,用于最低和最高可用内存区域位置。

    【讨论】:

    • 我想你的意思是sbrk,而不是strpbrk,它是一个字符串解析函数。 :-)
    • @R..:是的,你是对的,它是sbrk()。答案更正。 :)
    【解决方案2】:

    有 dlmalloc 内部工作原理的描述(glibc、uClibc 和许多其他地方使用的 malloc() 实现)here

    类 Unix 操作系统有两个主要接口用于请求/释放内存:

    • brk() 扩展/收缩数据段。
    • mmap()/munmap() 请求/释放额外的内存映射。

    Windows API 实际上类似于 malloc()/free(),具有 HeapAlloc()/HeapFree() 之类的功能。

    【讨论】:

    • Glibc 的 mallocdlmalloc 有很大的不同。
    【解决方案3】:

    操作系统分配页面,然后将其返回给 malloc/free,然后将这些页面从内存中分解为请求大小的块。操作系统可以分配用户地址空间中尚未请求的任何页面。没有堆段。分配的内存位于操作系统确定的任何位置。

    【讨论】:

    • 很好,那么保护是如何工作的呢?当我们动态分配内存时,只有我们的进程可以访问它,如果其他人试图在那里执行读/写操作,就会发生错误。页面是否标记为属于某个进程?
    • @grigory,没有。页在页表中被标记为有效或无效(x86 上的 P 或 V 位)PTE 也有一个 R/W 位。一组“活动”页表在进程上下文切换时“切换”到新活动进程的那些。每个进程都有自己的页目录(== 一组页表,每个都包含一组页+属性)
    • @Grigory:我的进程的页面对于其他进程不存在——它们是虚拟的。操作系统将虚拟页面映射到真实页面。您确实需要检查虚拟内存。
    • @Alex:实际上,在某些架构中,它们被标记为属于特定进程(MIPS 的 TLB 有一个 ASID 字段,可以将其视为一种 PID 缓存)。
    猜你喜欢
    • 2011-03-19
    • 2017-03-09
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 2012-10-25
    • 1970-01-01
    相关资源
    最近更新 更多