const_cast和射击自己的脚

时间:2016-04-16 22:09:42

标签: c++ gcc const-cast

我意识到这会导致未定义的行为:

const int x = 12;
*const_cast<int*>(&x) = 13;

但是gcc是否做了什么来防止这种情况杀死你,或者只是让你退后一步说'#34;嘿,你知道的更好&#34;。

也许它只是默默地删除整个程序中的const修饰符或其他东西(我不知道我只是在这里猜测)。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

实际上,你可以抛弃指针的常量:

  

5.2.11 / 7 根据对象的类型,通过指针,左值或指向数据成员的指针进行写操作   抛弃const限定符的const_cast 可能生成未定义的   行为

如果引用的对象是const,则这是未定义的行为

  

7.1.6.1/4:除了可以修改任何声明为mutable(7.1.1)的类成员之外,任何在其生命周期内修改const对象的尝试   (3.8)导致未定义的行为。

未定义的行为是......未定义:

  

1.3.24:此国际标准没有要求的行为(...)允许的未定义的行为范围从忽略   这种情况完全具有不可预测的结果,表现得很好   在翻译或程序执行过程中以文件的方式   环境的特征(有或没有发行   诊断消息),终止翻译或执行(用   发布诊断信息。)

所以,让我们想象一下可能会发生什么:可能它会起作用,也可能是段错误(例如,因为const数据将存储在const内存段中),可能会无法正常工作正如预期的那样(例如,写入被忽略),您可能会在编译时收到警告或错误。所以最好是避免这个!

当天的报价:&#34; C让您轻松拍摄自己的脚; C ++让它变得更难,但当你这样做时,你的整条腿就会被打破&#34; - Bjarne Stroustrup

答案 1 :(得分:0)

gcc因遇到UB时经常改变实际行为而闻名。版本1尝试运行nethack然后打印“99瓶”。我记得在某些时候,当gcc开始在类似

的代码中优化条件时,Linux内核中出现了一个关键漏洞
int x = s->x;
if(s != NULL) {

因为它假定当你取消引用指针时,你知道它是非NULL(否则它是标准的UB)。

答案 2 :(得分:0)

未定义行为的部分原因是允许编译器执行任何操作。我会留下其他人来引用标准,并专注于你问题中的哲学。

一般来说,声明变量const,抛弃const,然后做一些修改const变量的事情是编译器不会做任何特别保护的事情的一个方面你 - 毕竟,如果你正在做这些事情,你可能会有许多不同的事情,编译器(或开发它的程序员)没有理由假设它们。

在您的示例中,定义x的代码(与仅仅声明它不同)可能与使用const_cast以修改它的代码位于不同的编译单元中。 (这取决于源文件中的声明,定义和代码的组织方式)。

gcc是一个编译器,除了正在编译的编译单元之外,它主要不会达到项目的编译单元。这意味着它无法一般地检测到这种情况,并且无法确保在一个编译单元中发生的事情与另一个编译单元中发生的事情是一致的(即以保护您的方式)。例如,它可以基于x12的假设优化一个编译单元中的一个函数,以便在另一个函数中执行语句*const_cast<int*>(&x) = 13之后该函数永远不会改变其行为