C++ Linux下C语言中字符数组和指针的分段错误
因此,我有以下计划:C++ Linux下C语言中字符数组和指针的分段错误,c++,c,linux,segmentation-fault,elf,C++,C,Linux,Segmentation Fault,Elf,因此,我有以下计划: int main(){ char* one = "computer"; char two[] = "another"; two[1]='b'; one[1]='b'; return 0; } 它在“one[1]='b'”行上分段故障,这是有意义的,因为指针“one”指向的内存必须位于只读内存中。然而,问题是为什么行“two[1]='b'”没有故障?查看gcc的程序集输出: .file "one.c" .section
int main(){
char* one = "computer";
char two[] = "another";
two[1]='b';
one[1]='b';
return 0;
}
它在“one[1]='b'”行上分段故障,这是有意义的,因为指针“one”指向的内存必须位于只读内存中。然而,问题是为什么行“two[1]='b'”没有故障?查看gcc的程序集输出:
.file "one.c"
.section .rodata
.LC0:
.string "computer"
.LC1:
.string "another"
.text
.globl main
.type main, @function
main:
我们看到这两个字符串都在rodata部分,因此它们是只读的。那么,“二[1]这句话是怎么来的呢='b'不segfault?
one
直接指向只读页中的字符串。另一方面,two
是在堆栈上分配的数组,并用一些常量数据初始化。在运行时,可执行文件的只读部分中的字符串将复制到堆栈中。您正在修改的是co该字符串在堆栈上的py,而不是只读内存页
从更高的层次来看,从语言的角度来看,“abcd”
是一个类型为const char*
的表达式,而不是char*
。因此,修改这样一个表达式所指向的值会导致未定义的行为";仅将指向字符串的指针存储在变量中(不安全,因为它正在丢弃const
modifier)。chartwo[]=“某物”代码>完全不同。它实际上是声明一个数组并初始化它,很像inta[]={1,2,3}代码>。此处引号中的字符串是初始化表达式。在rodata部分中看到的“另一个”是将在初始化时复制到数组two
中的内容。另一方面,字符串“computer”的地址将分配给一个
因此,one
指向一个只读段(因此写入时为segfault),而two
将在堆栈上分配,然后将“另一个”复制到堆栈中 第二个表单通过复制文本字符串创建数组
这相当于:
char two[] = {'a', 'n', 'o', 't', 'h'. 'e', r', '\0'};
可以使用变量初始化字符数组,例如
char c = 'a';
char two[] = {'a', 'n', c, '\0'};
哇!我已经用C语言编程5年了,我不知道char[]
复制了常量数据。我一直认为[]
只是一种更奇特的写作方式*
。谢谢大家!+1我经常写charstr[]={“某物”}
试图使关联更清晰。另请参见不同但相关的问题