正确性和不可变分配对象

在最近的讨论中(参见对这个答案的评论),R ..建议永远不要为指针到const类型创建别名,因为你无法在一致的C程序中轻松地释放引用的对象(请记住: free()采用非常量指针参数 和C99 6.3.2.3仅允许从非合格到合格的转换 )。

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

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

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

要解除分配这样的对象,库必须丢弃const限定符; 据我所知,以下内容

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

是有效的C; 如果foo参数另外restrict ,它将只是无效。

然而,抛弃const看起来有些黑客攻击。

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

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

转换是在6.5.4中处理的,我没有看到任何会限制你从任何指针到const ,它本身不是const限定的(void*) 。 恰恰相反

除了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指针,供他使用。

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

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