正确性和不可变分配对象

时间:2010-10-22 18:50:26

标签: c pointers const

在最近的讨论中(请参阅this answer的注释),R ..建议永远不要为指针到const类型创建别名,因为您将无法轻松释放引用的对象在一个符合C的程序中(请记住:free()采用非const指针参数和C99 6.3.2.3只允许从非限定转换为限定

C语言显然假定任何已分配对象的所有者存在,即某人必须存储指向该对象的非const指针,并且该人负责释放。

现在,考虑一个库分配和初始化从用户空间代码不可修改的对象,因此函数调用总是返回const - 限定指针。

显然,库是对象的所有者,并且应该保留非const指针,这有点傻,因为用户已经提供了完全有效但指针的const副本每个图书馆电话。

要解除分配此类对象,库必须放弃const限定符;据我所知,以下

void dealloc_foo(const struct foo *foo)
{
    free((void *)foo);
}

是有效的C;如果foo参数另外restrict - 合格。

,它将无效

然而,抛弃const似乎有些骇人听闻。

除了从库函数的所有返回值中删除const之外还有另一种方法,它会丢失有关对象可变性的任何信息吗?

3 个答案:

答案 0 :(得分:4)

我在6.3.2.3中没有读到相同的内容。该段是关于隐式发生并且不需要演员表的转换。因此,可能不允许从指针到const对象的隐式转换,但这并未说明显式转换。

在6.5.4中处理了强制转换,我没有看到任何会限制你从任何指向const的强制转换的东西,而const本身不是(void*)符合{{{} 1}}。相反,它说

  

涉及指针的转化,   除了允许的地方   的约束   6.5.16.1,应通过明确的演员表明。

所以我读到那里,如果你明确地做事,他们是允许的。

所以我认为以下是完全有效的

char const *p = malloc(1);
free((void*)p);
<德尔> 6.5.4 forbits将是以下内容     char * const p = malloc(1);     自由((无效*)P); / *的表达式是const限定的* /

作为旁注,对于你的第二个想法,一个库返回一个指针到const限定的对象然后被置于调用者的责任中,对我来说没什么意义。任

  • 库返回指向的指针 内部对象,然后它应该 将它指向“const指向弱点” 保护,呼叫者不 改变它,或
  • 图书馆刚刚返回 分配的对象落入 来电者的责任。然后呢 应该不在乎是否 调用者更改它,因此它可能会返回 指向非限定对象的指针。如果是来电者 然后想要确保 内容不是偶然的 被覆盖或他可能的东西 将其分配给const指针,用于 他的用途。

答案 1 :(得分:2)

如果对象真的是不可变的,为什么要给用户指向它的对象并冒险成为腐败对象的机会?将对象地址保留在表中,向用户返回一个不透明句柄(整数表索引?)并接受库例程中的句柄。

答案 2 :(得分:1)

如果返回const - 限定指针,则语义是不允许函数的调用者以任何方式修改对象。这包括释放它,或将它传递给你的库中的任何功能,而这些功能将反过来释放它。是的我知道你可以抛弃const限定符,但是你违反了const暗示的合同。