繁体   English   中英

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

[英]Segmentation Fault With Char Array and Pointer in C on 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'行不存在段错误”呢?

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

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

在rodata部分中看到的“另一个”是初始化时将在数组two复制的内容。 另一方面,字符串“ computer”的地址将被分配给一个。

因此, one指向只读段(因此指向写段),而two将分配到堆栈上,然后将“另一个”复制到该段中。

第二种形式通过复制文字字符串创建一个数组。

它等效于:

char two[] = {'a', 'n', 'o', 't', 'h'. 'e', r', '\0'};

您可以使用变量来初始化字符数组,例如

char c = 'a';
char two[] = {'a', 'n', c, '\0'};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM