【问题标题】:Heap memory exploration with malloc使用 malloc 进行堆内存探索
【发布时间】:2016-07-18 18:25:48
【问题描述】:

我编写了一个输入 3 个数字的程序:

    1. malloc() 在堆中分配的内存大小
    1. 两个int

如果q 是一个unsigned char 指针,它会将q[i]=bq[min] 传递到q[max]

我认为堆是按页划分的,第一次调用malloc() 会给出一个指向我的进程页的第一个字节的指针。那么为什么如果尝试获取q[-1] 我的进程没有被杀死呢?

然后我尝试了另一个指针p,我注意到两个指针之间有32字节的距离,为什么它们不相邻?

我注意到的最后一件事是p[-8]=q[-40(-32-8)]q[-8] 都有数字33 00100001(所有其他字节都设置为0),这意味着什么?

谢谢!

【问题讨论】:

  • 思考未定义行为的含义。请指出标准中需要特定动态内存分配方案的部分。甚至不需要基于堆的机制。

标签: c malloc heap-memory


【解决方案1】:

我认为堆是按页面划分的,并且第一次调用 malloc 会给出一个指向我的进程页面的第一个字节的指针。那么为什么如果尝试获取 q[-1] 我的进程没有被杀死呢?

很可能是因为您的malloc 实现在那里存储了一些东西。可能是块的大小。

然后我尝试了另一个指针p,我注意到两个指针之间有32字节的距离,为什么它们不相邻?

同样的原因。您的实现可能将块的大小存储在块中它返回的地址之前。

我注意到的最后一件事是 p[-8]=q[-40(-32-8)] 和 q[-8] 都有数字 33 (00100001),这意味着什么?

这可能对您的malloc 实现有意义。但是如果不查看实现,您无法真正分辨出什么。

【讨论】:

  • 我用这个版本的gcc gcc (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609
  • 我可以去 q[-50] 甚至更多,并且进程不会被杀死
  • @sworwitz 实现可能会分配大块,将它们拆分,然后首先给出最后一个块。除了查看实现之外,真的没有办法确定。
【解决方案2】:

标准库在调用 main 之前使用堆,因此您所做的任何事情都不会在干净的堆上。
堆实现通常在分配开始时使用大约 2 个指针,总大小通常与 2 个指针对齐。
堆实现通常在每次系统分配开始时使用大量字节,有时可能接近页面大小。
堆分配在比页面大得多的块中,在 Windows 上至少有 16 个页面。
堆可以与其他分配相邻,在 Linux 上,它出现在主可执行文件之后,因此下溢不会崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-19
    • 2021-11-18
    • 2020-11-12
    • 2011-04-21
    • 2021-03-02
    • 2017-09-24
    • 1970-01-01
    相关资源
    最近更新 更多