比较已释放的指针是否会调用 UB? [英] Does comparing a pointer that has been free'd invoke UB?

查看:22
本文介绍了比较已释放的指针是否会调用 UB?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一个相当普遍的模式,例如在 hexchat(可能无法编译,另请参见 插件文档.另请注意hexchat_plugin_get_info 一直没有被使用,所以为了简单起见我省略了它):

This seems to be a fairly common pattern e.g. in hexchat (may not compile, see also plugin docs. also note that hexchat_plugin_get_info hasn't been used in forever so I'm omitting it for simplicity):

static hexchat_plugin *ph;
static int timer_cb(void *userdata) {
    if (hexchat_set_context(ph, userdata)) { /* <-- is this line UB? */
        /* omitted */
    }
    return 0;
}
static int do_ub(char *word[], char *word_eol[], void *userdata) {
    void *context = hexchat_get_context(ph);
    hexchat_hook_timer(ph, 1000, timer_cb, context);
    hexchat_command(ph, "close"); /* free the context - in practice this would be done by another plugin or by the user, not like this, but for the purposes of this example this simulates the user closing the context. */
    return HEXCHAT_EAT_ALL;
}
int hexchat_plugin_init(hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg) {
    *plugin_name = "do_ub";
    *plugin_desc = "does ub when you /do_ub";
    *plugin_version = "1.0.0";
    ph = plugin_handle;
    /* etc */
    hexchat_hook_command(ph, "do_ub", 0, do_ub, "does UB", NULL);
    return 1;
}

timer_cb 中的行导致 hexchat 将(在此示例中可能已释放 - 在此示例中绝对已释放,请参阅 do_ub 中的注释)指针与另一个指针进行比较,如果你从 here (, hexchat_set_context) 你最终会在 这里(hexchat.c#L191,is_session).要调用此代码,请在 hexchat 中运行 /do_ub.

The line in timer_cb causes hexchat to compare the (potentially free'd - definitely free'd in this example, see the comment in do_ub) pointer with another pointer, if you follow from here (plugin.c#L1089, hexchat_set_context) you'll end up in here (hexchat.c#L191, is_session). To invoke this code, run /do_ub in hexchat.

相关代码:

int
hexchat_set_context (hexchat_plugin *ph, hexchat_context *context)
{
    if (is_session (context))
    {
        ph->context = context;
        return 1;
    }
    return 0;
}

int
is_session (session * sess)
{
    return g_slist_find (sess_list, sess) ? 1 : 0;
}

这种东西是UB吗?

推荐答案

在指针指向的对象到达生命周期结束后使用指针的值是不确定,如C11 标准草案 6.2.4p2(对象的存储持续时间)(重点是我的):

Using a value of a pointer after the object it is pointing to have reached it's lifetime end is indeterminate as stated in the C11 Standard draft 6.2.4p2 (Storage durations of objects) (the emphasis is mine):

对象的生命周期是程序执行期间的一部分保证为其保留哪些存储空间.一个对象存在,有一个常量地址,并保留其最后存储的值在其整个生命周期中.如果一个对象在它的外部被引用生命周期,行为是未定义的.一个指针的值变成不确定当它指向(或刚刚过去)的对象到达生命周期结束.

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

并且使用它的值(仅用于任何事物)是一种显式的未定义行为,如附件 J.2(未定义行为):

And using it's value (just for anything) is an explicit undefined behavior as stated in Annex J.2(Undefined behavior):

在以下情况下行为未定义:[...]使用指向生命周期已结束的对象的指针的值(6.2.4).

The behavior is undefined in the following circumstances: [...] The value of a pointer to an object whose lifetime has ended is used (6.2.4).

这篇关于比较已释放的指针是否会调用 UB?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆