const_cast 用法给我运行时异常

const_cast usage giving me runtime exception

我刚刚开始 learning/exploring 关于 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" 存储在内存中的某处不能 modified.It 如果有人可以对此进行更多说明,那就太好了。

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

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

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

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

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

一般情况下最好不要使用const_cast除非你非常非常清楚自己在做什么。根据我的经验,这主要发生在与采用 char * 而不是 const char *.

的编写糟糕的(通常是 C)API 接口时

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

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

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

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

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

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