谁抛出分段错误?

时间:2011-03-01 05:04:19

标签: c unix data-structures operating-system

鉴于以下计划。

 int main() {
 char *str = "hello word";
 str[0] = 'a';
 return 0;
 }

上述程序会引发分段错误。我知道它会抛出,因为只读段包含hello世界,并且无法修改。如果在L1缓存(处理器内部)中完成从“h”变为“a”的存储指令,并且仅当页面从L3刷新到主存时MMU才会进入图像,几乎立即抛出分段故障。

以下代码实际上做同样的事情,不会导致任何分段错误。为什么呢?

 int main() {
 char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
 str[0] = 'a';
 return 0;
 }

2 个答案:

答案 0 :(得分:3)

处理器缓存具有与每个缓存行关联的标记,这些标记告诉它应用于当前在该缓存行中保存的内存的权限。因此,在尝试写入高速缓存时,(通常)将立即捕获写入只读存储器的尝试;它不会等到该缓存行被刷新到主存储器。

就两个例子之间的差异而言,它非常简单:第一个定义了一个静态分配的字符串文字。尝试修改该字符串文字会导致未定义的行为。第二个定义了一个初始化为特定值的char数组 - 但在初始化之后,它几乎与任何其他数组一样。特别是,修改数组内容的结果已经明确定义。

答案 1 :(得分:2)

在第二部分,你正在复制。虽然在第一个你不是。

char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};

这里str是在堆栈上创建的数组。要str,正在复制内容。怎么进 -

char *str = "hello word";

str指向驻留在不可修改部分的数据。所以,你不能和尝试时的结果分段错误。


评论说明

我不认为,原始数据类型C和C ++会改变它的规则。来自ISO / IEC 14882:2003(E),第8.5.2节

1. A char array (whether plain char, signed char, or unsigned char) can be 
   initialized by a string- literal (optionally enclosed in braces); a wchar_t 
   array can be initialized by a wide string-literal (option- ally enclosed in 
   braces); successive characters of the string-literal initialize the members of 
   the array.

     [Example:
           char msg[] = "Syntax error on line %s\n"; shows a character array 
           whose members are initialized with a string-literal. Note that because 
           ’\n’ is a single character and because a trailing ’\0’ is appended, 
           sizeof(msg) is 25. 
     ] 

2. There shall not be more initializers than there are array elements. 

    [Example:
          char cv[4] = "asdf" ;// error is ill-formed since there is no space for the implied trailing ’\0’. 
    ]

因此,示例2清除了疑问。