【问题标题】:const_cast usage giving me runtime exceptionconst_cast 用法给我运行时异常
【发布时间】:2016-03-13 08:52:22
【问题描述】:

我刚刚开始学习/探索 const_cast 并尝试使用它,但发现在使用 const_cast 后,如果我尝试修改数据会出现运行时错误。

基本上我是个东东像

void main()
{
const char* str = "Hello";
char* mstr = const_cast<char*>(str);
mstr[1] = 'R';//<----- i get runtime exception on this line
}

发生这种情况是因为字符串“Hello”被存储在内存中某个无法修改的地方。如果有人能对此进行更多说明,那就太好了。

【问题讨论】:

  • 您正在修改不应该修改的数据,并告诉编译器会拒绝您这样做“我不在乎”。那你为什么想知道?

标签: c++ c++11 casting constants const-cast


【解决方案1】:

根据定义,字符串文字是const,因此对其进行任何修改都会产生未定义的行为。

您正在使用const_cast 创建一个指向char(即mstr)的非const 指针,编译器允许您通过它修改字符串文字。

这样做不会改变修改字符串文字会产生未定义行为的基本事实。 const_cast 所做的只是给你一个指针,你可以用它来修改字符串文字而不会引起编译器的抱怨。编译器不需要对字符串文字做任何事情(例如,将其存储在可修改的内存中)以使该操作变得有效。因此,通过mstr 修改字符串文字仍然是未定义的行为。未定义行为的一种可能症状是运行时错误。

【讨论】:

    【解决方案2】:

    当你以你所做的方式声明一个字符串时,编译器可以用它做一些你可能意想不到的事情。这些包括字符串合并(多个相同的字符串实际上只存储一次),以及存储在写保护的内存区域中(注意:不需要执行这些操作,但可以)。

    在您的情况下,看起来字符串存储在写保护的内存中。通过使用 const_cast 告诉编译器忽略这一点,将触发 CPU 异常,这将导致您的程序终止。

    不过有一个简单的解决方案,就是以 可修改的方式声明您的字符串:

    char str [] = "Hello";
    char* mstr = str;
    mstr[1] = 'R'; 
    

    现在它是一个数组,您可以根据需要进行合法修改。不会发生字符串合并,数据也不会存储在写保护内存中——事实上你也不再需要 const_cast。

    一般来说最好不要使用 const_cast,除非你非常非常清楚自己在做什么。以我的经验,这主要发生在与使用char * 而不是const char * 的编写不佳的(通常是C)API 接口时。

    【讨论】:

    • 我没有对此投反对票,但 OP 的问题与const_cast 相关,在此答案中没有正确用法以及他/她偏离该用法的位置。只是在黑暗中开枪,但我猜这可能是下跌的原因。
    • 啊,可爱。所以我被否决了,然后有人几乎逐字复制我的答案(具有完全相同的信息内容),它被接受并获得+2。谢谢大家,这真的有助于我未来在这里回答问题的愿望......
    • 说什么?我有当前接受的答案和+2。我回答的内容与你的不同,我当然没有抄袭你。我也没有否决这个问题的任何答案。
    • 不攻击你个人彼得;在我写的时候,有另一个答案被接受(不是你),当时它与我的几乎相同 - 相同的解释和相同的源代码。我写了第一个答案,我认为它解决了问题并以合理的方式提供了解决方案。它被投票否决为-2,然后另一个人来复制它并得到+2。如果事实证明这在这个网站上是“正常的”,那么我就完成了贡献。让我们先看看吧。
    【解决方案3】:

    通常,数据段是可读写的,因为 vars 的值可以在运行时更改或修改。这与只读的 .rodata 段形成对比,后者包含静态常量而不是变量;

    ...
    .file   "main.cpp"
    .text
    .Ltext0:
        .section    .rodata
    .LC0:
    .string "Hello"
    .text
    ...
    

    它还与代码段 .text 段形成对比,后者在许多架构上是只读的。未初始化的数据,包括变量和常量,都在 BSS 段中。 The structure of executable file. 随意手动查看 asm 代码,这是了解实际情况的最有效方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-04
      • 2018-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-03
      • 2014-02-26
      • 2013-04-06
      相关资源
      最近更新 更多