55 votes

Déréférencement d'un pointeur sur 0 dans C

Parfois, les données en mémoire l'adresse 0x0 est très précieux -- prendre x86 en mode réel IVT comme un exemple connu: il commence à 0x0 et contient des pointeurs vers des gestionnaires d'interruption: un dword à 0x00 est un pointeur vers une division par zéro gestionnaire d'erreur.

Cependant, C11 langue standard interdit de déférence pointeurs null [WG14 N1570 6.5.3.2], qui sont définis comme des pointeurs initialisé avec des 0 ou des pointeurs initialisé avec un pointeur null [WG14 N1570 6.3.2.3], effectivement interdit le premier octet.

Comment le fait de 0x0 quand c'est nécessaire?

47voto

Keith Thompson Points 85120

C ne pas interdire le déréférencement de pointeur null, il ne fait que comportement indéfini.

Si votre environnement est telle que vous êtes en mesure de déréférencer un pointeur contenant l'adresse 0x0, alors vous devriez être en mesure de le faire. La norme du langage C ne dit rien sur ce qui va se passer quand vous le faites. (Et dans la plupart des environnements, le résultat sera un plantage du programme.)

Un exemple concret (si je me souviens bien): Sur le 68k-Soleil 3 ordinateurs, déréférencement d'un pointeur null n'est pas la cause d'un piège; au lieu de cela, le système d'exploitation stockée une valeur de zéro à l'adresse de mémoire à zéro, et le déréférencement d'un pointeur null (qui fait référence à l'adresse zéro) qui donnerait la valeur zéro. Que signifie, par exemple, qu'un programme C peut traiter un pointeur null comme un pointeur valide pour une chaîne vide. Certains logiciels, intentionnellement ou non, dépend de ce comportement. Cela a exigé beaucoup de nettoyage lors du portage de logiciels pour le SPARC-Soleil 4, pris au piège sur pointeur null déréférence. (Je me souviens de la lecture à ce sujet, mais j'ai été incapable de trouver une référence, je vais mettre à jour ce si je peux le trouver.)

Notez que le pointeur null est pas nécessairement l'adresse zéro; plus précisément, la représentation d'une valeur null peut ou ne peut pas être tous les bits à zéro. Très fréquemment, mais il n'est pas garanti. (Si elle ne l'est pas, alors l'entier-à-pointeur de conversion de (void*)0 est non-trivial.)

L'article 5 de la comp.lang.c FAQ traite des pointeurs null.

19voto

Greg Hewgill Points 356191

Comment les gens utilisent-ils réellement 0x0 quand c'est nécessaire?

Soit par:

  • écrire le code requis en langage assembleur, ou
  • écrire le code en C et vérifier que le compilateur génère le langage d'assemblage correct pour l'opération souhaitée

9voto

bmargulies Points 49855

La déclaration:

char * x = 0;

ne pas forcément mettre 0 x 0 dans x. Il met l'définis valeur de pointeur null pour le courant de l'architecture et du compilateur dans x.

Maintenant, dans la pratique, tous les compilateurs / processeurs observée dans l'usage commun ne finissent par mettre 32 (ou 64) 0 bits en une ligne dans un registre ou un emplacement de stockage en réponse à cette déclaration, de sorte que, si l'adresse mémoire 0 est utile, alors, comme d'autres l'ont indiqué, vous êtes coincé à l'aide formellement un comportement indéfini. Cependant, en une fois, il y a du matériel pour lequel un "pointeur null" a été quelque peu motif que c'était pas tous les zéros, et, qui sait, il y a peut être encore une fois.

2voto

haccks Points 33022

Le système d'exploitation d'utiliser un tableau de pointeurs sur des routines d'interruption d'appel appropriée de l'interruption(s). Généralement, dans la plupart des système d'exploitation) tableau de pointeurs est stocké en mémoire basse (la première quelques centaines de lieux, etc), Ces endroits tenir les adresses des routines de service d'interruption pour les divers périphériques.

Ainsi, lorsque vous vous

char *ptr = 0x0; 

il est alors probable que vous sont en cours d'initialisation de votre pointeur avec l'adresse d'une routine de service d'interruption. Un déréférencement (ou de modifier) un emplacement de mémoire qui appartient au système d'exploitation les plus susceptibles de causer planter le programme.
Donc, c'est mieux de ne pas initialiser un pointeur à l' 0x0 et de déréférencement d'elle jusqu'à ce que vous avez la confirmation qu'il n'appartient pas à l'OS.

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