60 votes

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 / numérise 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!
 

45voto

Lundin Points 21616

Un pointeur est un type de variable spécifique, qui ne peut contenir l'adresse d'une autre variable. Il ne peut pas contenir toutes les données. Vous ne pouvez pas "copier/stocker des données dans un pointeur" - qui n'a pas de sens. Vous ne pouvez définir un pointeur sur les données utilisées ailleurs.

Cela signifie que, pour un pointeur pour être valable, il doit toujours pointer vers un emplacement mémoire valide. Par exemple, il pourrait point mémoire allouée sur la pile:

{
  int data = 0;
  int* ptr = &data;
  ...
}

Ou de la mémoire allouée dynamiquement sur le tas:

int* ptr = malloc(sizeof(int));

C'est toujours un bug d'utiliser un pointeur avant il a été initialisé. Il n'est pas encore au point de la mémoire.

Ces exemples peuvent tous conduire à des incidents de programme ou d'autres types de comportement inattendu, comme une "segmentation défauts":

/*** examples of incorrect use of pointers ***/

// 1.
int* bad;
*bad = 42;

// 2.
char* bad;
strcpy(bad, "hello");

Au lieu de cela, vous devez vous assurer que le pointeur de points (assez) de la mémoire allouée:

/*** examples of correct use of pointers ***/

// 1.
int var;
int* good = &var;
*good = 42;

// 2.
char* good = malloc(5+1); // allocates memory for 5 characters and 1 terminator
strcpy(good, "hello");

Notez que vous pouvez également définir un pointeur à un domaine bien défini de "nulle part", c'est en le laissant point d' NULL. Cela en fait un pointeur null, ce qui est un pointeur qui est garanti de ne pas pointer à n'importe quel mémoire valide. Ceci est différent de quitter le pointeur complètement non initialisé.

int* p1 = NULL; // pointer to nowhere
int* p2;        // uninitialized pointer, pointer to "anywhere", cannot be used yet

Pourtant, si vous essayez d'accéder à la mémoire pointée par un pointeur null, vous pouvez obtenir des problèmes similaires lors de l'utilisation d'un pointeur non initialisé: les accidents ou la segmentation des défauts. Dans le meilleur des cas, votre système d'avis que vous essayez d'accéder à l'adresse null, puis lance un "null pointer exception".

La solution pour null pointer exception des bugs est le même: vous devez définir le pointeur dans la mémoire avant de l'utiliser.


Pour en savoir plus:

Les pointeurs pointant sur des données non valides
Comment accéder à une variable locale d'une fonction différente en utilisant les pointeurs?
Une variable de la mémoire accessible à l'extérieur de son champ d'application?

Erreur de Segmentation et causes
Ce qui est une erreur de segmentation?
Pourquoi j'obtiens une erreur de segmentation lors de l'écriture d'une chaîne initialisée avec "char *s", mais pas "char s[]"?
Quelle est la différence entre char s[] et char *s?
La Liste définitive des Raisons Communes pour la Segmentation des Défauts
Ce qui est une erreur de bus?

4voto

lonesomecodeboy Points 59
  1. Les pointeurs seul point à un emplacement de mémoire. Vous avez créé un pointeur, mais vous n'avez pas se lier à un emplacement de mémoire encore. strcpy vous souhaite de passer deux pointeurs (d'abord il ne faut pas être constante) qui pointent vers deux tableaux de caractères comme cette signature:

    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'à arriver à un caractère de nouvelle ligne (*vous pouvez également ajouter d'autres espaces comme "%[^\t\n]s"(tabulation, saut de ligne) ou "%[^ \t\n]s" (espace, tabulation, saut de ligne)).

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

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

0voto

anoopknr Points 1639

Cela se produit parce que vous avez pas alloué de la mémoire pour le pointeur char* ptr. Dans ce cas, vous devez allouer dynamiquement de la mémoire pour le pointeur.

Deux fonctions malloc() et calloc() peut être utilisé pour l' dynamic memory allocation.

Essayez ce code:

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

Lors de l'utilisation de *ptr plus de ne pas oublier de libérer la mémoire allouée pour *ptr .Cela peut être fait en utilisant free() fonction.

  free(ptr);  // deallocating memory.

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

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

Dans la plupart des cas, une"segmentation fault" se produit en raison d'une erreur dans l'allocation de la mémoire ou de la matrice de hors limite les cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X