174 votes

Comment déboguer les erreurs de corruption de tas ?

Je débogue une application C++ multithread (native) sous Visual Studio 2008. En des occasions apparemment aléatoires, j'obtiens une erreur "Windows a déclenché un point d'arrêt..." avec une note indiquant que cela pourrait être dû à une corruption du tas. Ces erreurs ne font pas toujours planter l'application immédiatement, mais il est probable qu'elle se plante peu après.

Le gros problème de ces erreurs est qu'elles n'apparaissent qu'après que la corruption a eu lieu, ce qui les rend très difficiles à repérer et à déboguer, surtout dans une application multithread.

  • Quelles sortes de choses peuvent provoquer ces erreurs ?

  • Comment puis-je les déboguer ?

Les conseils, outils, méthodes, éclairages... sont les bienvenus.

8voto

StackedCrooked Points 12247

Un petit conseil, que j'ai obtenu de Détection de l'accès à la mémoire libérée c'est ça :

Si vous voulez localiser l'erreur rapidement, sans vérifier chaque qui accède au bloc de mémoire bloc mémoire, vous pouvez définir le pointeur mémoire à une valeur invalide après avoir libéré le bloc bloc :

#ifdef _DEBUG // detect the access to freed memory
#undef free
#define free(p) _free_dbg(p, _NORMAL_BLOCK); *(int*)&p = 0x666;
#endif

5voto

Shing Yip Points 913

Le meilleur outil que j'ai trouvé utile et qui a fonctionné à chaque fois est la révision du code (avec de bons réviseurs de code).

En dehors de la révision du code, j'essaierais d'abord de Page Heap . L'installation de Page Heap prend quelques secondes et, avec un peu de chance, elle pourrait permettre de localiser votre problème.

Si vous n'avez pas de chance avec Page Heap, téléchargez Outils de débogage pour Windows de Microsoft et apprenez à utiliser le WinDbg. Désolé de ne pas pouvoir vous aider plus spécifiquement, mais le débogage d'une corruption de tas multithreads est plus un art qu'une science. Cherchez sur Google "WinDbg heap corruption" et vous devriez trouver de nombreux articles sur le sujet.

4voto

dreadpirateryan Points 200

Vous pouvez également vérifier si vous effectuez la liaison avec la bibliothèque d'exécution C dynamique ou statique. Si vos fichiers DLL sont liés à la bibliothèque d'exécution C statique, les fichiers DLL ont des tas séparés.

Par conséquent, si vous créez un objet dans une DLL et essayez de le libérer dans une autre DLL, vous obtiendrez le même message que celui que vous voyez ci-dessus. Ce problème est référencé dans une autre question de Stack Overflow, Libération de la mémoire allouée dans une autre DLL .

3voto

JaredPar Points 333733

Quel type de fonctions d'allocation utilisez-vous ? J'ai récemment rencontré une erreur similaire en utilisant les fonctions d'allocation de type Heap*.

Il s'est avéré que j'ai créé par erreur le tas avec l'option HEAP_NO_SERIALIZE option. Cela fait essentiellement fonctionner les fonctions Heap sans sécurité thread. C'est une amélioration des performances si elle est utilisée correctement, mais elle ne devrait jamais être utilisée si vous utilisez HeapAlloc dans un programme multithread [1]. Je ne mentionne ceci que parce que votre message mentionne que vous avez une application multithread. Si vous utilisez HEAP_NO_SERIALIZE quelque part, supprimez-le et cela résoudra probablement votre problème.

[1] Il existe certaines situations où cela est légal, mais cela nécessite de sérialiser les appels à Heap* et ce n'est généralement pas le cas pour les programmes multithreads.

0 votes

Oui : regardez les options de compilation de l'application et assurez-vous qu'elle est construite pour être liée à une version "multithread" de la bibliothèque d'exécution C.

0 votes

@ChrisW Pour les API de type HeapAlloc, c'est différent. Il s'agit en fait d'un paramètre qui peut être modifié au moment de la création du tas, et non au moment de la liaison.

0 votes

Oh. Je n'ai pas pensé que l'OP pouvait parler de ce tas, et non du tas dans le CRT.

3voto

Vladimir Obrizan Points 1381

Si ces erreurs se produisent de manière aléatoire, il est fort probable que vous ayez rencontré des erreurs de données. Veuillez vérifier : modifiez-vous les pointeurs de mémoire partagée de différents threads ? Intel Thread Checker peut aider à détecter de tels problèmes dans un programme multithread.

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