Linux上C字符串和指针的分段故障

cco*_*der 15 c c++ linux elf segmentation-fault

所以我有以下程序:

int main(){
  char* one = "computer";
  char two[] = "another";
  two[1]='b';
  one[1]='b';
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

它在"one [1] ='b'"这一行上有段错误,因为指针"one"所指向的内存必须位于只读内存中.然而,问题是为什么"2 [1] ='b'"行不是段错误?查看gcc的程序集输出:

.file   "one.c"
        .section        .rodata
.LC0:
        .string "computer"
.LC1:
        .string "another"
        .text
.globl main
        .type   main, @function
main:
Run Code Online (Sandbox Code Playgroud)

我们看到两个字符串都在rodata部分,因此它们是只读的.那么为什么"两个[1] ='b'这一行不会出现段错误?

Meh*_*ari 38

one直接指向位于只读页面中的字符串.另一方面,two是在堆栈上分配的数组,并使用一些常量数据进行初始化.在运行时,可执行文件的只读部分中的字符串将被复制到堆栈中.您要修改的是堆栈上该字符串的副本,而不是只读内存页面.

从更高层次的角度来看,从语言的角度来看,"abcd"是一种类型的表达const char*而不是char*.因此,修改此类表达式指向的值会导致未定义的行为.该语句char* one = "something";仅将指向字符串的指针存储在变量中(不安全,因为它正在抛弃const修饰符).的char two[] = "something";是完全不同的.它实际上是声明一个数组并初始化它,就像它一样int a[] = {1,2,3};.引号中的字符串是初始化表达式.

  • 哇...我已经用C编程了大约5年了,我不知道`char []`制作了一份常量数据.我一直以为`[]`只是写作`*`的一种更好的方式.谢谢!+1 (4认同)
  • 我经常写`char str [] = {"Something"};`以试图使关联更清晰. (3认同)