Кто выбрасывает ошибку сегментации? - PullRequest
3 голосов
/ 01 марта 2011

Учитывая приведенную ниже программу.

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

Вышеуказанная программа выдает ошибку сегментации. Я знаю, что он выбрасывает, потому что сегмент только для чтения содержит привет мир, и он не может быть изменен. Если инструкция сохранения, которая изменяется с «h» на «a», выполняется в кэше L1 (внутри процессора), и MMU появляется в кадре только тогда, когда страница сбрасывается из L3 в основную память, который почти сразу выдает ошибку сегментации.

Приведенный ниже код, который эффективно делает то же самое, не вызывает ошибок сегментации. Почему?

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

Ответы [ 2 ]

3 голосов
/ 01 марта 2011

Кэш процессора имеет теги, связанные с каждой строкой кэша, которые сообщают ему разрешения, примененные к памяти, в настоящее время хранящейся в этой строке кэша.Таким образом, попытка записи в постоянную память будет (обычно) перехватываться сразу после попытки записи в кэш;он не будет ждать, пока эта строка кэша будет сброшена в основную память.

Что касается разницы между двумя примерами, то она довольно проста: первый определяет статически размещенный строковый литерал.Попытка изменить этот строковый литерал приводит к неопределенному поведению.Второй определяет массив char, который инициализируется определенным значением - но после инициализации он в значительной степени похож на любой другой массив.В частности, результат изменения содержимого массива четко определен.

2 голосов
/ 01 марта 2011

Во втором вы делаете копию.В первом случае вы не.

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

Здесь str - массив, созданный в стеке.До str содержимое копируется.Как бы то ни было -

char *str = "hello word";

str указывает на данные, находящиеся в неизменяемой секции.Таким образом, вы не можете, и когда попытался результаты ошибки сегментации.


Описание для комментариев

Не думаю, для примитивных типов данных C иС ++ меняет свои правила.Из ИСО / МЭК 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 устраняет сомнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...