首页 > 解决方案 > 当 mprobe 被传递一个指向已释放内存块的指针时,它应该返回什么?

问题描述

mcheck的GNU libc手册页说 MCHECK_FREE 状态意味着“块已被释放”。这对我来说意味着该块被释放(至少)一次。这个答案似乎在代码示例中暗示相同。但是,Linux 手册页非常明确地指出 MCHECK_FREE 的意思是“一块内存被释放了两次”。我从上面的答案修改了代码示例,使其更具描述性:

#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>

void print_status(enum mcheck_status status)
{
    switch(status)
    {
        case MCHECK_DISABLED:
        printf("MCHECK_DISABLED\n");
        break;

        case MCHECK_OK:
        printf("MCHECK_OK\n");
        break;

        case MCHECK_HEAD:
        printf("MCHECK_HEAD\n");
        break;

        case MCHECK_TAIL:
        printf("MCHECK_TAIL\n");
        break;

        case MCHECK_FREE:
        printf("MCHECK_FREE\n");
        break;
    }
}

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    print_status(mprobe(f));

    free(f);

    print_status(mprobe(f));

    return 0;
}

当我运行此代码时,我得到以下输出:

MCHECK_OK
MCHECK_HEAD

这意味着在检查释放的块时,我显然得到了 MCHECK_HEAD 作为响应。这种行为可靠吗?期望一个块的头部在被释放时总是被破坏是否合理?是否有不同的 mcheck/mprobe 实现会返回 MCHECK_FREE?

标签: cmallocfree

解决方案


我通过电子邮件发送了一个 libc 开发人员邮件列表。我将我的问题分为 2 个问题,每个问题都得到了答复:

  1. 哪个手册(GNU 或 Linux)关于 MCHECK_FREE 是正确的?

它们都是正确的,但从略微不同的角度编写。

如果该块以前是空闲的,那么您应该返回 MCHECK_FREE。

但是,如果您无法检测到它之前由于损坏而被释放,那么您可能只能在损坏更改了有关状态信息的所有同位元数据的情况下返回 MCHECK_HEAD 作为默认结果。

  1. 通常期望 MCHECK_HEAD 将被返回是否合理 [在释放的指针上调用 mprobe 时]?

是的。


推荐阅读