C++ 为什么更改非常量字符时出现分段错误*?
使用此代码,我得到一个分段错误:C++ 为什么更改非常量字符时出现分段错误*?,c++,pointers,char,constants,C++,Pointers,Char,Constants,使用此代码,我得到一个分段错误: char* inputStr = "abcde"; *(inputStr+1)='f'; 如果代码为: const char* inputStr = "abcde"; *(inputStr+1)='f'; 我将得到“分配只读位置”的编译错误。 然而,对于第一种情况,没有编译错误;只是在实际发生赋值操作时出现的分段错误 有人能解释一下吗?即使“abcde”是一个字符串文字,不应该修改它,但您已经告诉编译器,您不在乎它,让一个非常量字符*
char* inputStr = "abcde";
*(inputStr+1)='f';
如果代码为:
const char* inputStr = "abcde";
*(inputStr+1)='f';
我将得到“分配只读位置”的编译错误。
然而,对于第一种情况,没有编译错误;只是在实际发生赋值操作时出现的分段错误
有人能解释一下吗?即使“abcde”
是一个字符串文字,不应该修改它,但您已经告诉编译器,您不在乎它,让一个非常量字符*
指向它
编译器会很高兴地假设您知道自己在做什么,而不会抛出错误。但是,当您确实尝试修改字符串文字时,代码很有可能在运行时失败。字符串文字通常存储在只读内存中。试图更改此内存将杀死您的程序
这里有一个很好的解释:标准规定,无论您是否将字符串文本标记为常量,都不允许直接修改字符串文本: 是否所有字符串文字都是不同的(即存储在非重叠的 对象)是实现定义的。试图修改字符串文字的效果未定义 事实上,在C语言中(与C++不同),字符串文字不是常量,但仍然不允许对其进行写入 这种对书写的限制允许进行某些优化,例如沿以下行共享文字:
char *ermsg = "invalid option";
char *okmsg = "valid option";
其中,
okmsg
实际上可以指向ermsg
中的'v'
字符,而不是一个独特的字符串。这大部分是古代历史;很久以前,字符串文字不是常量
然而,大多数现代编译器将字符串文本放入只读内存(通常是程序的文本段,代码也存在于此),任何更改字符串文本的尝试都会产生核心转储或等效内容
有了G++,您肯定会得到编译警告(-Wall
,如果默认情况下没有启用)。例如,在MacOS X 10.6.7上编译的G++4.6.0(但在10.7上运行)产生:
因此,默认情况下会启用警告。发生的情况是编译器将常量
“abcde”
放在某个只读内存段中。您将(非常量)char*inputStr
指向该常量,然后将kaboom和segfault指向该常量
要吸取的教训:不要调用未定义的行为
编辑(精化)
然而,对于第一种情况,没有编译错误,只是在实际发生赋值操作时出现了分段错误
您需要启用编译器警告。始终将编译器警告设置得尽可能高。字符串文字虽然正式为非常量,但几乎总是存储在只读内存中。在您的设置中,显然只有声明为const char array时才会出现这种情况
请注意,标准禁止您修改任何字符串文字。这将在代码段中创建:
char *a = "abcde";
本质上是常数
如果要编辑它,请尝试:
char a[] = "abcde";
以下是标准在第[2.13.4/2]节中对字符串文字的说明: 不以u、u或L开头的字符串文字是普通字符串文字,也称为窄字符串文字。普通字符串文字的类型为“array of n const char”,其中n是如下定义的字符串大小;它具有静态存储持续时间(3.7),并用给定的字符初始化 因此,严格地说,“abcde”是有类型的
const char[6]
现在,代码中发生的是对
char*
这样作业就可以了。之所以如此,很可能是因为与C的兼容性。请看下面的讨论:
一旦转换完成,您就可以在语法上自由地修改文本,但它失败了,因为编译器将文本存储在不可写的内存段中,这是标准本身允许的。Ritchie单词中字符串文本的一点历史。 主要是关于K&R 1中字符串文字的起源和演变。 希望这能澄清关于常量和字符串文字的一两件事 发信人:丹尼斯·里奇 主题:Re:历史问题:字符串文本。 日期:1998年6月2日 新闻组:comp.std.c 在C89委员会工作时,可写 字符串文字不是“遗留代码”(Margolin)是什么标准 存在(K&R 1)非常明确(A.2.5)的 字符串只是初始化静态数组的一种方式。 正如巴里指出的,有一些(mktemp)例程 他们利用了这个事实 我没有出席委员会对这一问题的审议 这一点很重要,但我怀疑BSD实用程序用于摆弄 用于移动字符串初始化的汇编代码 以文本代替数据,并实现 事实上,文字字符串并没有被覆盖,而是更多 比gcc的一些早期版本更重要 我认为委员会可能遗漏了什么 没有找到一个公式来解释 字符串文字在常量方面的行为。 也就是说,如果“abc”是类型为的匿名文本 常量字符[4] 然后是它的所有属性(包括 能够使其成为只读,甚至可以共享其存储 与其他出现的相同文字)几乎相同 解释道 这方面的问题不仅仅是相对较少的人 实际写入字符串文字的位置,但很多 更重要的是,为作业制定可行的规则 指向常量的指针,特别是函数的实际 事实上,委员会知道 他们制定的规则不能要求强制执行 对现有世界中的每个func(“字符串”)进行诊断 所以他们决定离开普通字符数组的“…” 输入,但说一个是不需要写在上面的 顺便说一句,这张便条不是故意的
char*
Dennis