Pourquoi l’écriture sur un littéral de chaîne dans ce programme segfault?

#include void main() { char *p="nyks"; p[2]='n'; printf("%s",p); } 

Cela se bloque avec une erreur de segmentation . Quelqu’un peut-il expliquer pourquoi?

La norme indique que les chaînes littérales sont définies const . Vous ne pouvez pas le changer.

Le compilateur place le littéral dans une section de mémoire en lecture seule. Vous pouvez sortir l’assemblage et l’observer. Si vous utilisez GCC, cela se fait via le drapeau -s. Il placera la chaîne dans une section .rodata.

Essayer d’écraser un littéral de chaîne est un comportement indéfini. C99 §6.4.5 / 6:

Si le programme tente de modifier un tel tableau, le comportement n’est pas défini.

Ceci est indiqué dans l’Annexe J.2 (comportement non défini).

Si vous le faites plutôt:

 char p[] = "nyks"; 

vous pouvez allouer et initialiser un tableau de caractères automatique (stack). Dans ce cas, il est parfaitement correct de modifier des éléments.

D’autres réponses indiquent la vue du sharepoint vue des normes, mais voici pourquoi elle se bloque.

Les compilateurs mettent généralement les littéraux de programme, en particulier les chaînes, dans une mémoire en lecture seule. La mémoire est marquée en lecture seule par le système d’exploitation. Toute tentative d’écriture sur celle-ci sera bloquée et, sur votre plate-forme, c’est ce que la défaillance de segmentation indique; une tentative d’opération sur une mémoire non autorisée. L’autre type de panne associé à une mauvaise utilisation de la mémoire est une erreur de bus, qui indique généralement soit un access à la mémoire non aligné, soit une écriture sur une page qui n’est pas mappée du tout. Pour le code C, la différence est presque entièrement théorique (certaines implémentations de langage utilisent ces erreurs pour les aider à gérer la mémoire).

Notez que le recouvrement des écritures en lecture seule est indépendant de la sémantique officielle de la langue. Même si un caractère char* désigne, vous ne pouvez toujours pas l’écrire. Traitez toujours les littéraux de programme comme s’ils indiquaient une mémoire constante et vous ne vous tromperiez pas (ils ne le sont pas par défaut car il est nécessaire de prendre en charge la compatibilité avec les programmes plus anciens).

Cela se traduit (essentiellement) par:

  #include const char privatessortingng[5] = {"nyks"}; void main() { char *p = const_cast(privatessortingng); p[2]='n'; printf("%s",p); } 

Le compilateur est autorisé à placer privatessortingng endroit où vous n’avez qu’un access en lecture. Il effectue la const_cast pour assurer la compatibilité ascendante avec les programmes écrits auparavant. Il s’agissait d’un mot clé const.

La valeur est un littéral de chaîne qui ne peut pas être modifié car les littéraux sont stockés dans une mémoire à lecture seule, essayez p [] à la place. Les erreurs de segmentation sont généralement dues à une mauvaise utilisation des pointeurs.

Les littéraux de chaîne ne sont pas modifiables … La possibilité d’écrire char *p="nyks"; est en fait un trou de système de type en C.