我刚刚开始学习/探索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”存储在内存中无法修改的位置。如果有人可以为此提供更多信息,那就太棒了。
答案 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代码,这是了解其实际情况的最有效方式。