2013-08-22 4 views
-1

Cela fonctionne:Segmentation fault avec strcpy()

int main() 
{  
    char *t = "Hello"; 
    t = "World"; 
    printf("%s", t); 
} 

Mais cela donne une erreur de segmentation:

int main() 
{ 
    char *t = "Hello"; 
    strcpy(t, "World"); // the only difference 
    printf("%s", t); 
} 

Pourquoi?

+0

J'utilise le compilateur gcc – user2076561

+1

'char * t =" Hello ";" est un pointeur qui pointe vers une chaîne littérale. Vous pouvez l'assigner librement à une autre chaîne littérale mais ne peut pas stocker certaines données (chaîne par exemple) dans cette mémoire.C'était l'essence de la réponse ci-dessous que je pense que quelqu'un downvoted - Si vous êtes le seul - s'il vous plaît allez et revenez-y. –

Répondre

4

Dans le premier exemple, le pointeur t est amené à pointer sur une constante de chaîne "Hello", puis immédiatement après à la constante de chaîne "World"; la dernière valeur est ensuite imprimée.

Le code du second exemple se bloque avec segfault car les constantes de chaîne ne sont pas inscriptibles. (strcpy essaie de modifier la mémoire qui contient le texte "Hello"). GCC place les constantes de chaîne dans une section en lecture seule, sauf si elles sont compilées avec -fwriteable-strings.

Le code

char *test = "Hello"; 

signifie que le compilateur + lieu de linker une chaîne d'octets « Bonjour \ 0 » dans une section en lecture seule, et les test des points dans le premier caractère de celui-ci. Toute tentative d'écriture à travers ce pointeur serait sévèrement punie par le système d'exploitation.

D'autre part

char test[] = "Hello"; 

déclare un tableau de 6 caractères, avec une valeur initiale de ({ 'H', 'e', 'l', 'l', 'o', '\0' }).

Certains anciens programmes supposaient que les constantes de chaîne étaient accessibles en écriture; GCC doit donc prendre en charge la compilation de ces programmes avec le commutateur de ligne de commande -fwriteable-strings.

+0

alors qu'en est-il le premier programme (t = "monde") – user2076561

+0

@ user2076561 Parce que 'p' est un pointeur, ce n'est pas la même chose que la chaîne littérale –

+0

@ user2076561 Dans le premier programme, vous n'écrivez pas' 'World '' '' '' '' '' '' '' '' '' '' '' '' '' '' Hello'', vous faites le Pointeur ailleurs. –

3

La première modifie la valeur de t pour pointer de l'adresse "Hello" à l'adresse "World". La deuxième tente d'écraser les données "Hello" lui-même.

1

"Bonjour" est une constante de chaîne. Il n'est pas destiné à être écrit, par la définition de constante. Dans votre premier exemple, 't' est un pointeur, et il peut pointer (être assigné) une chaîne de caractères constante.

5

Les chaînes que vous définissez explicitement - par ex. "Hello" - sont généralement placés dans une zone de mémoire en lecture seule. Ces chaînes ne peuvent pas être modifiées.

Dans le premier exemple, vous ne modifiez pas la chaîne "Hello" dans la chaîne "World". Vous ré-attribuez t de sorte que points à "Monde" au lieu de "Bonjour". La chaîne "Hello" est toujours en attente, intacte, dans la mémoire en lecture seule.

est ici l'état initial:

t -> "Hello" 
    "World" 

Voici le deuxième état:

 "Hello" 
t -> "World" 

Dans le second exemple, vous essayez de remplacer la chaîne "Bonjour". Cela ne peut pas être fait.Vous devez vraiment changer votre déclaration de char *t à const char *t. Je pense que GCC peut être configuré pour appliquer ceci.

1

Dans char *t="Hello"t affectez "Hello" en lecture seule. Donc, écrire à l'emplacement readonly fait une erreur de segmentation.

Il existe une différence entre l'affectation et la copie.

Premier exemple vous essayez d'affecter l'adresse d'une autre chaîne à t.

Dans le deuxième exemple, vous essayez d'écrire en lecture seule.

utilisez char t[] = "Hello". Ici t peut être écrasera

explication plus Here

2

L'affectation t = "World" ne change que le pointeur, alors que le strcpy change la mémoire à laquelle les points t. Les littéraux de chaîne peuvent vivre dans un segment en lecture seule.

2

char* t est un pointeur. Dans le premier exemple, vous affectez simplement le pointeur d'une chaîne littérale à une autre: d'abord t pointé sur "Hello", puis "World". C'est parfaitement légal. Cependant, les littéraux de chaîne eux-mêmes sont des littéraux - ils ne peuvent pas être changés. Généralement, ils sont dans une section de mémoire en lecture seule. Dans le deuxième exemple, vous tentez de modifier ce qui se trouve dans la mémoire allouée à la chaîne littérale "Hello" en l'écrasant avec "World". C'est illégal et vous obtiendrez une erreur de segmentation.