【问题标题】:value of length(integer), used by the free pointer长度(整数)的值,由空闲指针使用
【发布时间】:2012-01-12 20:11:45
【问题描述】:

正如我们所知,free() 函数通过使用存储在 malloc 指针后面的前缀整数值知道要从 malloc 内存中释放多少内存。所以我尝试了这段代码,有两个疑问:

  1. 如果我malloc() 20 个字节,然后在递减的指针处打印整数值,则显示为 25 个字节。如果我malloc() 40 个字节,然后打印该值,那么我得到 49 个字节!

  2. 如果我尝试超越并在我的 malloc'd 空间之后打印值,每次我得到一个大整数值存储在 malloc'd 内存的最后一个旁边。那价值是什么?有什么特别的吗?

任何解释都将不胜感激。

int main()
{
    int i;
    int *ptr, *pr;

    ptr = (int *)malloc(20);
    pr = ptr;

    printf("value of ptr is %p", ptr);
    for(i = 0; i < 5; i++) {
        ptr[i] = i + 1;
    }

    printf("now the values in malloc'd memory is\n");
    for(i = 0; i < 5; i++) {
        printf("%d\n", ptr[i]);
    }

    printf("value of ptr is %p\n", ptr);
    pr--;
    for(i = 0; i < 20; i++) {
        printf("value of pr at address  %p  is  %d\n", pr, *pr);
        pr++;
    }

    return 0;
}

【问题讨论】:

  • 不,我们不知道。
  • 扩展 Kerrek SB 所说的内容,是什么让您认为这就是您的 malloc 实现跟踪大小的方式?
  • 您是否仅出于学术原因使用它? C 或 C++ 中没有任何规则可以保证您所说的内容。
  • @kerrek SB,@aix,@Renan Greinert 请原谅这个错误,我只是一个初学者,我说的是我从书本或互联网上读到的……这是一种方法吗了解 free() 是如何实现的?如果是的话,那么你们可以请人吗?看看我的疑问..
  • 我希望之前的值实际上表示大小为 24 或 48,最低位用作标志以表示某事或其他(可能是分配了内存)。您看到的“大值”可能是未初始化的内存,或者是内存分配器数据结构中其他位置的指针。 Kerrek 是正确的,实际上我们不知道细节,但原则上我们可以检查 glibc 中 malloc 的实现。您应该这样做,查看代码(和 cmets)比浏览数据更有启发性。

标签: c linux malloc free


【解决方案1】:
  1. 我们不知道 malloc 在内部是如何工作的。它可以在运行时库的版本之间更改。它没有(到目前为止),这不是赌博的理由。

  2. 我们不应依赖任何特定实现的特定幕后行为。除非您愿意为了某些值得的目的而放弃一般性,否则只依赖于记录的功能。

事实上,大多数malloc 实现确实在分配给程序的区域之前分配了额外的几个字的开销。开销允许管理堆。但是大小字段是 4 字节之前还是 16 字节?它是 32 位值吗?也许它是按比例缩放的段落数(16 字节条目),就像在 iRMX86 上一样。开销区域是否包含前向链接后向链接?也许有一个带有调试版本库的名称检查字段。

也许它的实现类似于 Cyber​​/NOS 上的 Snobol-68:一个结构数组,其中包含指向数据及其大小的指针。程序“指针”实际上是数组中项目的索引。对于缓存和预读而言,这是一种特别有效的结构。

有太多可能的变化,任何持久的计划都不应该依赖这些细节。

您可能会考虑编写一个lengthof(ptr) 函数以包含在运行时库中,该函数返回malloc() 请求的字节数,或者可能实际分配的字节数。

【讨论】:

    【解决方案2】:

    大多数malloc 实现可能都有某种方法来查找指针参数的分配大小。

    但是,这样做的方式是实现私有的,并且一些malloc 实现并不总是为每个区域分配前缀标头

    实现malloc 的一个常见技巧是处理不同的分配大小。例如,它可以有不同的处理方式

    1. malloc 两个单词或更少(即 2*sizeof(void*)),因为这种情况非常常见(例如,指针的单链表,如 Lisp 中的 cons 单元格)。
    2. malloc 的小区域,大小小于阈值,通常是页面大小 - 在 Linux 上的 getpagesize(2) 系统调用的意义上,通常为 4kbytes。
    3. malloc 的大区域,大于页面大小

    一些实现会考虑实际地址,例如有一个内部区域(页面段)专用于对,另一个分配区域专用于大小为2^n3*2^n 的小区域(例如n&gt;2 &amp;&amp; n&lt;10),以及实际分配在各自区域中的大对象。然后malloc 实现有一些内部哈希表映射地址(每个低 16 位全为零)到 arenas。

    所以你不应该假设每个 malloc-ed 区域之前都有开销。这可能是错误的。如果您需要这样的假设,请使用操作系统调用(例如 Linux 上的 mmap(2))编写自己的 malloc 等效(或替换)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-03
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多