【发布时间】:2019-05-03 06:50:57
【问题描述】:
我的用例如下。
我开发了一个库,其中一些加载的插件可以创建对象(由库使用malloc() 分配),而其他一些插件可以读取这些对象的属性但不能修改它们。
对我来说,这是一个非const API 用于创建/编写端和const API 用于读取端的情况,例如:
// writer API
struct obj *obj_create(void);
void obj_set_some_property(struct obj *obj, int property);
// reader API
int obj_get_some_property(const struct obj *obj);
库将struct obj *(由作者方创建)转换为const struct obj *(读者方可用)。
我的问题是那些对象也有引用计数,读者端可以调用你典型的引用计数递增/递减函数。这些函数需要修改对象。
我的问题是:在这种特定情况下,引用计数递增/递减函数在内部接受 const struct obj * 并丢弃 const 是否安全?请注意,如果计数达到零,引用计数递减函数也可能销毁(释放)对象。
我知道 §6.7.3¶5 说:
如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的对象,则行为未定义。
我只是想不通用 const 限定类型定义 是什么意思。如果我的对象是堆分配的,这是否适用?例如,我完全理解为什么使用文字字符串指针 (.rodata) 会是 UB。但是如果对象一开始就被创建为非const 呢?
strchr() 是一个众所周知的将const 强制转换的示例:它接受const char * 并返回char *,它指向const char * 参数内。考虑到 §6.7.3¶5,这在法律上如何?
【问题讨论】:
-
这完全取决于原始指针是如何分配的。
const限定符主要允许编译器在尝试修改时通过警告来帮助您,并允许编译器根据您不会修改对象的承诺进一步优化。正如您所发现的,您可以通过抛弃const限定符来打破这个承诺,但是.. 那么您就靠自己了,您必须保证内存是可变的,在free的情况下,之前分配有@987654340 @。抛弃的需要通常表明代码设计存在缺陷。 -
强制转换不会修改对象。抛弃 const 绝不是 UB。如果您继续使用强制转换的结果来修改 const 对象,则可能是 UB。
-
语言律师的东西:重要的是对象的有效类型。 malloc 指向的数据在您对数据进行左值访问之前没有类型 - 在这种情况下,“有效类型”将成为您用于访问的类型。而且我认为不可能使用 const 限定类型(?)进行左值访问。
标签: c casting constants undefined-behavior const-correctness