【问题标题】:Segmentation Fault With Char Array and Pointer in C on LinuxLinux 上 C 中字符数组和指针的分段错误
【发布时间】:2010-12-18 21:18:31
【问题描述】:

所以我有以下程序:

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 部分,所以它们是只读的。那么“two[1]='b'这行怎么没有段错误?

【问题讨论】:

标签: c++ c linux segmentation-fault elf


【解决方案1】:

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

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

【讨论】:

  • 哇...我已经用 C 语言编程大约 5 年了,我不知道 char[] 复制了常量数据。我一直认为[] 只是写* 的一种更好的方式。谢谢! +1
  • 我经常写char str[] = {"Something"};,试图让关联更​​清晰。
【解决方案2】:

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

所以,one 指向一个只读段(因此写入时的段错误),而two 将在堆栈上分配,然后“另一个”将被复制到其中。

【讨论】:

    【解决方案3】:

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

    相当于:

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

    可以用变量初始化字符数组,如

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-18
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      • 2013-10-26
      • 1970-01-01
      相关资源
      最近更新 更多