web-dev-qa-db-fra.com

Manière générale de résoudre une erreur: la pile autour de la variable 'x' était corrompue

J'ai un programme qui me demande l'erreur dans VS2010, dans le débogage: 

Error: Stack around the variable 'x' was corrupted

Cela me donne la fonction où un débordement de pile est susceptible de se produire, mais je ne peux pas voir visuellement où est le problème.

Existe-t-il un moyen général de déboguer cette erreur avec VS2010? Serait-il possible d'indiquer quelle opération d'écriture écrase la mémoire de pile incorrecte?

14
lezebulon

Existe-t-il un moyen général de déboguer cette erreur avec VS2010?

Non, il n'y en a pas. Ce que vous avez fait est en quelque sorte d'invoquer un comportement indéfini. La raison pour laquelle ces comportements ne sont pas définis est que le cas général est très difficile à détecter/diagnostiquer. Parfois, il est impossible de le faire.

Cependant, il existe un nombre assez restreint de problèmes qui causent généralement votre problème:

  • Mauvaise gestion de la mémoire:
    • Supprimer quelque chose deux fois,
    • En utilisant le type de suppression incorrect (free pour quelque chose alloué avec new, etc.),
    • Accéder à quelque chose après que sa mémoire ait été effacée.
  • Renvoyer un pointeur ou une référence à un local.
  • Lecture ou écriture après la fin d'un tableau.
12
David Hammen

Cela peut être causé par plusieurs problèmes, généralement difficiles à voir:

  • doubles suppressions
  • delete une variable affectée avec new[] ou delete[] une variable affectée à new
  • delete quelque chose alloué avec malloc
  • delete une variable de stockage automatique
  • retour d'un local par référence

Si ce n'est pas immédiatement clair, je mettrais la main sur un débogueur de mémoire (je peux penser à Rational Purify pour Windows).

8
Luchian Grigore

En fait, ce que vous voyez est assez informatif, vous devriez vous enregistrer près de x emplacement de variable pour toute activité pouvant causer cette erreur.

Voici comment vous pouvez reproduire une telle exception:

int main() {
    char buffer1[10];
    char buffer2[20];
    memset(buffer1, 0, sizeof(buffer1) + 1);
    return 0;
}

va générer (VS2010):

Échec de la vérification au moment de l'exécution n ° 2 - La pile autour de la variable 'buffer1' était corrompue.

manifestement, memset a écrit 1 caractère plus qu'il ne le devrait. VS avec option\GS permet de détecter de tels débordements de mémoire tampon (que vous avez activés). Pour plus d’informations, lisez ceci: http://msdn.Microsoft.com/en-us/library/Aa290051 .

Vous pouvez par exemple utiliser le débogueur et le code pas à pas, chaque fois que vous regardez le contenu de votre variable, son évolution. Vous pouvez également tenter votre chance avec des points d'arrêt de données, vous définissez un point d'arrêt lorsque certains emplacements de mémoire changent et le débogueur s'arrête à ce moment-là, ce qui peut éventuellement vous indiquer où se trouve le problème. Mais cela pourrait ne pas fonctionner avec le drapeau\GS. 

Pour détecter les débordements de tas, vous pouvez utiliser l'outil gflags.

3
marcinj

Ce message peut également être dû à une violation des limites du tableau. Assurez-vous que votre fonction (et chaque fonction appelée, en particulier les fonctions membres pour les objets basés sur une pile) obéit aux limites des tableaux pouvant être utilisés.

3
Omaha

Cette erreur m'a laissé perplexe pendant des heures. Je connais les causes possibles. Celles-ci sont déjà mentionnées dans les réponses précédentes, mais je n'alloue pas de mémoire, n'accède pas aux éléments d'un tableau, ne renvoie pas les pointeurs sur des variables locales. .

Puis finalement trouvé la source du problème:

*x++;

L'intention était d'incrémenter la valeur indiquée. Mais en raison de la priorité précédée de ++, déplacer le pointeur x vers l'avant puis * ne fait rien, puis écrire dans *x endommagera le canari de la pile si le paramètre provient de la pile, ce qui fait grief à VS.

Le changer en (*x)++ résout le problème.

J'espère que cela t'aides.

1
Calmarius

Voici ce que je fais dans cette situation:

Définissez un point d'arrêt à un emplacement où vous pouvez voir la valeur (correcte) de la variable en question, mais avant que l'erreur se produise. Vous aurez besoin de l'adresse mémoire de la variable dont la pile est corrompue. Parfois, je dois ajouter une ligne de code pour que le débogueur me donne l'adresse facilement (int * x = & y)

À ce stade, vous pouvez définir un point d'arrêt de la mémoire (Débogage-> Nouveau point d'arrêt-> Nouveau point d'arrêt des données)

Hit Play et le débogueur devraient s'arrêter lorsque la mémoire est écrite. Recherchez la pile (le mien insère généralement un code d'assemblage) pour voir comment on appelle. 

0
Ben

Je suis généralement la variable avant la variable qui se plaint qui m'aide généralement à résoudre le problème. Mais cela peut parfois être très complexe sans aucun indice comme vous l'avez vu. Vous pouvez activer le menu Débogage >> Exceptions et cocher la case "Exceptions Win32" pour intercepter toutes les exceptions. Cela ne détectera toujours pas ces exceptions, mais cela pourrait intercepter autre chose qui pourrait indirectement indiquer le problème.

Dans mon cas, cela était dû à la bibliothèque que j'utilisais. Le fichier d’en-tête que j’ai inclus dans mon projet ne correspond pas tout à fait au fichier d’en-tête de cette bibliothèque (sur une ligne).

Il y a une erreur différente qui est aussi liée:

0xC015000F: le contexte d'activation en cours de désactivation n'est pas le plus récemment activé un.

Lorsque j'en ai eu marre de recevoir le message mystérieux sur la pile corrompue sur mon ordinateur sans informations de débogage, j'ai essayé mon projet sur un autre ordinateur et il me donnait plutôt le message ci-dessus. Avec la nouvelle exception, j'ai été en mesure de trouver la solution. 

0
zar

J'ai rencontré ce problème lorsque j'ai créé un tableau de 13 éléments avec le pointeur, puis j'ai essayé de définir le 14ème élément. Changer le tableau en 14 éléments a résolu le problème. J'espère que cela aide certaines personnes ^ _ ^

0