一尘不染

Linux上使用C的Char数组和指针进行分段错误

linux

所以我有以下程序:

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

它在“ one [1] =’b’”行上进行段错误,这是有道理的,因为指针“ one”指向的内存必须位于只读内存中。但是,问题是,为什么“ two [1]
=’b’” segfault行没有出现?查看gcc的程序集输出:

.file   "one.c"
        .section        .rodata
.LC0:
        .string "computer"
.LC1:
        .string "another"
        .text
.globl main
        .type   main, @function
main:

我们看到两个字符串都在rodata部分中,因此它们是只读的。那么,为什么“ two [1] =’b’行不存在段错误”呢?


阅读 260

收藏
2020-06-02

共1个答案

一尘不染

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

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

2020-06-02