const_cast用法给我运行时异常

时间:2016-03-13 08:52:22

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

我刚刚开始学习/探索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”存储在内存中无法修改的位置。如果有人可以为此提供更多信息,那就太棒了。

3 个答案:

答案 0 :(得分:2)

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

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

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

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

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

一般情况下,最好不要使用const_cast,除非你非常清楚地知道你在做什么。根据我的经验,这种情况主要发生在与错误编写的(通常是C)API接口时,char *代替const char *

答案 1 :(得分:2)

根据定义,字符串文字是const,因此任何修改都会给出未定义的行为。

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

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

答案 2 :(得分:1)

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

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

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