Почему я получаю ошибку сегментации при записи в строку, инициализированную "char * s", но не "char s []"? - PullRequest
268 голосов
/ 02 октября 2008

Следующий код получает ошибку сегмента в строке 2:

char *str = "string";
str[0] = 'z';  // could be also written as *str = 'z'
printf("%s\n", str);

Хотя это прекрасно работает:

char str[] = "string";
str[0] = 'z';
printf("%s\n", str);

Протестировано с MSVC и GCC.

Ответы [ 17 ]

4 голосов
/ 02 октября 2008

 char *str = "string";

строка определяет указатель и указывает на литеральную строку. Буквенная строка недоступна для записи, поэтому, когда вы делаете:

  str[0] = 'z';

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

Линия:

char str[] = "string";

выделяет массив символов, а копирует буквенную строку в этот массив, который полностью доступен для записи, поэтому последующее обновление не представляет проблем.

3 голосов
/ 02 октября 2008

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

В первом примере вы получаете указатель на эти постоянные данные. Во втором примере вы инициализируете массив из 7 символов с копией данных const.

2 голосов
/ 20 января 2012
// create a string constant like this - will be read only
char *str_p;
str_p = "String constant";

// create an array of characters like this 
char *arr_p;
char arr[] = "String in an array";
arr_p = &arr[0];

// now we try to change a character in the array first, this will work
*arr_p = 'E';

// lets try to change the first character of the string contant
*str_p = 'G'; // this will result in a segmentation fault. Comment it out to work.


/*-----------------------------------------------------------------------------
 *  String constants can't be modified. A segmentation fault is the result,
 *  because most operating systems will not allow a write
 *  operation on read only memory.
 *-----------------------------------------------------------------------------*/

//print both strings to see if they have changed
printf("%s\n", str_p); //print the string without a variable
printf("%s\n", arr_p); //print the string, which is in an array. 
1 голос
/ 02 октября 2008

Во-первых, str - это указатель, который указывает на "string". Компилятору разрешено помещать строковые литералы в места в памяти, в которые вы не можете писать, но можете только читать. (Это действительно должно было вызвать предупреждение, так как вы присваиваете const char * для char *. У вас были отключены предупреждения или вы просто проигнорировали их?)

Во-вторых, вы создаете массив, то есть память, к которой у вас есть полный доступ, и инициализируете его с помощью "string". Вы создаете char[7] (шесть для букв, один для завершающего '\ 0'), и вы делаете с ним все, что захотите.

0 голосов
/ 03 января 2013
Ошибка сегментации

возникает, когда вы обращаетесь к памяти, которая недоступна.

char *str - указатель на строку, которая не может быть изменена (причина получения ошибки сегмента) ..

, тогда как char str[] является массивом и может быть изменяемым ..

0 голосов
/ 04 февраля 2019

Предположим, строки:

char a[] = "string literal copied to stack";
char *p  = "string literal referenced by p";

В первом случае, литерал должен быть скопирован, когда «а» входит в область видимости. Здесь «a» - это массив, определенный в стеке. Это означает, что строка будет создана в стеке, а ее данные скопированы из кодовой (текстовой) памяти, которая обычно доступна только для чтения (это зависит от реализации, компилятор может также поместить эти программные данные только для чтения в постоянную память) ).

Во втором случае p - это указатель, определенный в стеке (локальная область) и ссылающийся на строковый литерал (данные или текст программы), хранящиеся где-то еще. Обычно изменение такой памяти не является хорошей практикой и не поощряется.

0 голосов
/ 11 октября 2013

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

...