2009-11-20 5 views
14

J'ai donc le programme suivant:Segmentation Fault avec Array Char et pointeur en C sous Linux

int main(){ 
    char* one = "computer"; 
    char two[] = "another"; 
    two[1]='b'; 
    one[1]='b'; 
    return 0; 
} 

Il segfaults sur la ligne « un [1] = « b » » ce qui est logique car la mémoire le pointeur "un" pointe vers doit être en lecture seule. Cependant, la question est pourquoi la ligne "deux [1] = 'b'" segfault? En regardant la sortie de montage de gcc:

.file "one.c" 
     .section  .rodata 
.LC0: 
     .string "computer" 
.LC1: 
     .string "another" 
     .text 
.globl main 
     .type main, @function 
main: 

On voit que les deux chaînes sont dans la section Rodata donc ils sont en lecture seule. Alors, comment se fait-il que la ligne "two [1] = 'b' ne segfault pas?

+0

Voir aussi la question différente, mais liée http://stackoverflow.com/questions/ 1770062/defining-pointer-to-static-string/1770067 # 1770067 –

Répondre

35

one est directement sur la chaîne située dans une page en lecture seule. et est initialisé avec des données constantes Lors de l'exécution, la chaîne dans la section en lecture seule de l'exécutable sera copiée dans la pile.Ce que vous modifiez est la copie de cette chaîne sur la pile, pas la page de mémoire en lecture seule .

au point de vue de niveau supérieur, du point de vue linguistique, "abcd" est une expression de type const char* et non char*. Ainsi, la modification de la valeur pointée par un tel expression entraîne un comportement non défini. la déclaration char* one = "something"; stocke simplement le pointeur sur la chaîne dans une variable (imprécis car il supprime le modificateur const). Le char two[] = "something"; est totalement différent. En fait, il déclare un tableau et l'initialise, un peu comme int a[] = {1,2,3};. La chaîne entre guillemets est l'expression d'initialisation.

+3

Wow ... J'ai programmé en C depuis environ 5 ans et je ne savais pas que 'char []' faisait une copie des données constantes. J'ai toujours pensé que [] était juste une façon plus élégante d'écrire "*". Je vous remercie! +1 – Earlz

+3

J'écris souvent 'char str [] = {" Quelque chose "};' dans le but de rendre l'association plus claire. – LnxPrgr3

+0

@ Mehrdad: Crystal clear !! :) –

1

Le "autre" que vous voyez dans la section rodata est ce qui sera copié dans le tableau two quand il sera initialisé. D'autre part l'adresse de la chaîne "ordinateur" sera affectée à un. Ainsi, one pointe vers un segment en lecture seule (et donc la segfault sur l'écriture) tandis que two sera alloué sur la pile, puis "un autre" sera copié dans celui-ci.

0

La seconde forme crée un tableau en copiant la chaîne littérale.

Il est équivalent à:

char two[] = {'a', 'n', 'o', 't', 'h'. 'e', r', '\0'}; 

Vous pouvez initialiser un tableau de caractères variables, telles que

char c = 'a'; 
char two[] = {'a', 'n', c, '\0'};