Почему запись в строковый литерал в этой программе на Си сегфо? - PullRequest
5 голосов
/ 03 сентября 2010
#include<stdio.h>

void main()
{
    char *p="nyks";

    p[2]='n';

    printf("%s",p);
}

Это происходит с ОТКЛ СЕГМЕНТАЦИИ .Может кто-нибудь объяснить, почему?

Ответы [ 6 ]

15 голосов
/ 03 сентября 2010

Неопределенное поведение пытаться перезаписать строковый литерал. C99 §6.4.5 / 6:

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

Это повторяется в Приложении J.2 (неопределенное поведение).

Если вместо этого:

char p[] = "nyks";

Вы можете выделить и инициализировать автоматический (стек) массив символов. В этом случае совершенно нормально модифицировать элементы.

7 голосов
/ 03 сентября 2010

Стандарт определяет, что литеральные строки определены const.Вы не можете изменить его.

Компилятор помещает литерал в раздел памяти только для чтения.Вы можете вывести сборку и наблюдать за этим.Если вы используете GCC, это делается с помощью флага -s.Это поместит строку в раздел .rodata.

3 голосов
/ 03 сентября 2010

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

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

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

1 голос
/ 31 января 2015

Значение является строковым литералом, который нельзя изменить, поскольку литералы хранятся в постоянной памяти, попробуйте вместо этого использовать p []. Ошибки сегментации обычно возникают из-за неправильного использования указателей.

1 голос
/ 03 сентября 2010

Это означает (по существу):

 #include<stdio.h>  
 const char privatestring[5] = {"nyks"};

 void main()  
 {  
    char *p = const_cast<char*>(privatestring); 
    p[2]='n';        

    printf("%s",p);        
 }        

Компилятору разрешено помещать privatestring где-то, где у вас есть только права на чтение.Он выполняет const_cast для обратной совместимости с программами, написанными до того, как это было ключевым словом const.

0 голосов
/ 03 сентября 2010

Строковые литералы не могут быть изменены ... Способность писать char *p="nyks"; на самом деле является дырой системы типов в C.

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