web-dev-qa-db-fra.com

Crash ou "erreur de segmentation" lorsque les données sont copiées/scannées/lues dans un pointeur non initialisé

Cette question est destinée à être utilisée comme référence pour toutes les questions fréquemment posées de la nature:

Pourquoi ai-je un crash mystérieux ou une "erreur de segmentation" lorsque je copie/analyse des données à l'adresse indiquée par un pointeur non initialisé?

Par exemple:

char* ptr;
strcpy(ptr, "hello world"); // crash here!

ou

char* ptr;
scanf("%s", ptr); // crash here!
36
Lundin
  1. Les pointeurs pointent uniquement vers un emplacement de mémoire. Vous avez créé un pointeur mais vous ne vous êtes pas encore lié à un emplacement de mémoire. strcpy souhaite que vous passiez deux pointeurs ( le premier ne doit pas être constant ) pointant vers deux tableaux de caractères comme celui-ci:

    char * strcpy ( char * destination, const char * source );
    

    exemple d'utilisation:

    char* ptr = malloc(32);  
    strcpy(ptr, "hello world");
    
    char str[32];  
    strcpy(str, "hello world");
    
  2. Vous pouvez essayer l'extrait de code suivant pour lire une chaîne jusqu'à atteindre le caractère de nouvelle ligne (* vous pouvez également ajouter d'autres caractères d'espacement tels que "%[^\t\n]s" ( tab, nouvelle ligne ) ou "%[^ \t\n]s" ( espace, tabulation, nouvelle ligne )).

    char *ptr = malloc(32);
    scanf("%31[^\n]", ptr);
    

    (Dans la vie réelle, n'oubliez pas de vérifier la valeur de retour de scanf()!!)

2
lonesomecodeboy

Cela est dû au fait que vous avez non alloué mémoire pour le pointeurchar* ptr ..____. Dans ce cas, vous devez allouer dynamiquement de la mémoire pour le pointeur.

Deux fonctions malloc() et calloc() peuvent être utilisées pour dynamic memory allocation.

Essayez ce code: -

  char* ptr;
  ptr = (char *) malloc(sizeof(char)*50); // allocate space for 50 characters.
  strcpy(ptr, "hello world");

Lorsque l'utilisation de *ptr est terminée, n'oubliez pas de désallouer de la mémoire allouée pour *ptr. Cela peut être fait à l'aide de la fonction free().

  free(ptr);  // deallocating memory.

La taille de la mémoire allouée dynamiquement peut être modifiée à l'aide de realloc().

  ptr = (char *)realloc(ptr, sizeof(char)*100);// allocate space for 0 characters.

Dans la plupart des cas "erreur de segmentation" est dû à une erreur dans allocation de mémoire ou tableau hors cas.

0
anoopknr

N'est-ce pas le cas, mais une situation qui se produit souvent au début est l'utilisation de guillemets simples et la tentative de définir un littéral de chaîne comme:

char ptr[5];
strcpy(ptr, 'hello'); // crash here!
            ^     ^   // because of ' instead "

Dans C 'h' est un littéral à caractère unique, tandis que "h" est un littéral de chaîne contenant un "h" et un terminateur nul/0 (c'est-à-dire un tableau à 2 caractères). De plus, en C, le type d'un littéral de caractère est le suivant: sizeof 'h' vaut 4 (sur 32 bits), alors que sizeof (char) vaut 1.

char h = 'h';
printf("Size: %d\n",sizeof(h));     //Size: 1
printf("Size: %d\n",sizeof('h'));   //Size: 4
0
Leonard Lepadatu