11
votes

La déréférance Les pointeurs supprimés entraînent toujours une violation d'accès?

J'ai un code C ++ très simple ici:

char *s = new char[100];
strcpy(s, "HELLO");
delete [] s;
int n = strlen(s);


3 commentaires

Il produit un comportement non défini, ce qui signifie que le programme peut faire tout ce qu'il veut. C'est un peu étrange qu'il ne tombe pas en dehors du débogueur, cependant. Que se passe-t-il réellement? S'il s'agit d'un programme de console, quelle est la sortie?


Prendre soin des pointeurs supprimés est en effet une douleur. C'est pourquoi vous devriez utiliser std :: vecteur ou dans ce cas particulier std :: string au lieu de nouveau [] . Vous ne devriez jamais avoir à utiliser Supprimer .


L'échantillon de code est une coupe de l'application réelle. Je reproduit un bug qui survient rarement, probablement uniquement lorsqu'un thread fait le Supprimer et une autre prenez la désarférence. Par conséquent, je veux un moyen de reproduire sincèrement cela. Et alors ne m'avez pas failli avec toutes ces réponses utiles :)


6 Réponses :


20
votes

Accéder à la mémoire à travers un pointeur supprimé est un comportement indéfini. Vous ne pouvez pas vous attendre à un comportement fiable / reproductible.

Très probablement il "fonctionne" dans le cas d'un cas car la chaîne est toujours "assise là" dans la mémoire désormais disponible - = mais vous ne pouvez pas compter sur cela. Vs remplit la mémoire avec des valeurs de débogage pour aider à forcer des accidents pour aider à trouver ces erreurs.


0 commentaires

5
votes

Dérariférant un pointeur après Supprimer est un comportement non défini - tout peut se produire, y compris mais non limité à:

  • Corruption de données
  • Violation d'accès
  • Aucun effet visible

    Les résultats exacts dépendront de multiples facteurs dont la plupart sont hors de votre contrôle. Vous serez bien mieux de ne pas déclencher un comportement non défini en premier lieu.


0 commentaires

2
votes

Habituellement, il n'y a pas de différence dans la mémoire allouée et libérée d'une perspective de processus. E.g Le processus n'a qu'une grande carte mémoire qui pousse à la demande.

La violation d'accès est causée par la lecture / écriture de la mémoire qui n'est pas disponible, utilisée de manière utilisée dans le processus. Divers utilitaires de débogage de la mémoire de temps d'exécution utilisent le mécanisme de pagination pour suivre les accès à la mémoire non valides sans la pénalité de temps d'exécution grave que la vérification de la mémoire logicielle aurait.

Quoi qu'il en soit, votre exemple ne prouve que qu'une erreur est parfois détectée lors de l'exécution du programme dans un environnement, mais non détectée dans un autre environnement, mais c'est toujours une erreur et le comportement du code ci-dessus n'est pas défini.


0 commentaires

10
votes

La différence est qu'un débogueur et des bibliothèques de débogage, et le code intégré en mode "débogage", aime briser des choses qui devraient casser. Votre code devrait casser (car il accède à la mémoire qu'il ne possède plus techniquement), il est donc plus facile de s'affranchir une fois compilé pour déboguer et courir dans le débogueur.

Dans la vraie vie, vous ne recevez généralement pas un avis aussi sévère. Tout ce genre de choses qui fait de la pause quand ils devraient au débogueur ... ce genre de choses cher. Il n'est donc pas coché comme strictement en libération. Vous pourriez être capable de 99 fois sur 100 pour vous éloigner de la libération de la mémoire et de l'accéder juste après, car les Libs d'exécution ne remettent pas toujours la mémoire au système d'exploitation immédiatement. Mais que la centième fois, soit la mémoire de la mémoire, soit un autre thread le possède maintenant et que vous obtenez la longueur d'une chaîne qui n'est plus une chaîne, mais une gamme de merde de 252462649-BYTE qui fonctionne en unallocated (et donc non Il est existant, autant que vous ou le runtime devrait se soucier de la mémoire. Et il n'y a plus qu'à rien pour vous dire ce qui vient d'arriver.

Alors ne fais pas ça. Une fois que vous avez supprimé quelque chose, considérez-le mort et parti. Ou vous allez gaspiller la moitié de votre vie suivant les heisenbugs.


1 commentaires

Belle référence aux heisenbugs: D



1
votes

L'exécutable avec les symboles de débogage est capable de détecter certains cas de violations d'accès. Le code pour détecter cela est contenu dans l'exécutable, mais ne sera pas déclenché par défaut.

Vous trouverez ici une explication de la façon dont vous pouvez contrôler le comportement en dehors d'un débogueur: http://msdn.microsoft.com/en-us/library/w500y392%28v=vs.80%29.aspx


0 commentaires

1
votes

Je veux aussi savoir si c'est possible reproduire sincèrement l'accès Accident de violation causé par l'accès Zone supprimée?

au lieu de la plaine Supprimer Vous pouvez envisager d'utiliser une fonction en ligne qui définit également la valeur du pointeur supprimé sur 0 / null. Cela se bloque généralement si vous y référez-le. Cependant, cela ne se plaint pas si vous la supprimez une seconde fois.

Ce genre de crash est-il rare dans vraie vie?

Non, ce type d'accident est probablement derrière la majorité des accidents que vous et je vois dans des logiciels.


0 commentaires