美文网首页
Linux C中的char数据和指针的段错误

Linux C中的char数据和指针的段错误

作者: 东东东东东东丶 | 来源:发表于2018-06-26 20:44 被阅读0次

    原文: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'"这行没有发生段错误呢?查看gcc的汇编输出:

    .file "one.c"

            .section        .rodata

    .LC0:

            .string "computer"

    .LC1:

            .string "another"

            .text

    .globl main

            .type  main, @function

    main:

    我们看到两个字符串都在 只读数据区域。那么为什么 “two[1]='b'”这行没有发生段错误呢?


    Answers1:

    one指针指向的stirng在只读页。另一方面,two是一个分配在栈上的数组,使用一些常量数据进行初始化。在运行期间,在只读区域的string会被拷贝一份到栈上。你修改的是string在栈上的拷贝,不是只读内存页。

    更高层次的看法,从语言的视角看。“abcd”是一个const char*而不是 char*。因此,修改这样的指针值的结果是未定义的。这个语句char* one = "something";,存储了一个指向字符串的指针(不安全的,它把const属性转换没了)。char two[] = "something";则是完全不同的。它实际上声明了一个数组并初始化了它,就像这样 int a[] = {1,2,3};。这里的引号里面的string是一个初始化表达式。


    Answers2:

    你看到的“another”在只读区域会被拷贝到数组 two中,在数组初始化的时候。另一方面,字符串“computer”的地址会被分配给one。

    因此,one是指向只读区域(在这里写会发生段错误),two会分配在栈上然后拷贝一份“another”。


    Answers3:

    第二个形式会创建一个数组并拷贝这个字符串:

    它等同于:

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

    你可以使用变量初始化字符数组,像这样:

    char c = 'a';

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

    相关文章

      网友评论

          本文标题:Linux C中的char数据和指针的段错误

          本文链接:https://www.haomeiwen.com/subject/jokuyftx.html