Je travaille sur un multithreading Application C++ qui corrompt le tas. Les outils habituels pour localiser cette corruption semblent être inapplicables. Les anciennes versions (18 mois) du code source présentent le même comportement que la version la plus récente, ce qui signifie que le problème existe depuis longtemps et qu'il n'a tout simplement pas été remarqué. beaucoup des changements de code dans le référentiel.
L'incitation au comportement de plantage est de générer un débit dans ce système - le transfert de données par socket qui est transformé en une représentation interne. Je dispose d'un ensemble de données de test qui provoquent périodiquement des exceptions dans l'application (à différents endroits, pour différentes raisons - y compris l'échec de l'allocation du tas, donc la corruption du tas).
Ce comportement semble lié à la puissance du processeur ou à la bande passante de la mémoire ; plus la machine dispose de l'un ou l'autre de ces éléments, plus il est facile de se planter. La désactivation d'un cœur hyperthreading ou d'un cœur double réduit le taux de corruption (mais ne l'élimine pas). Cela suggère un problème lié au timing.
Maintenant, voici le problème :
Lorsqu'il est exécuté sous un environnement de débogage léger (par exemple Visual Studio 98 / AKA MSVC6
), la corruption du tas est raisonnablement facile à reproduire - dix ou quinze minutes s'écoulent avant que quelque chose n'échoue de façon épouvantable et que des exceptions, telles que le message alloc;
lors de l'exécution sous un environnement de débogage sophistiqué (Rational Purify, VS2008/MSVC9
ou même Microsoft Application Verifier), le système devient limité par la vitesse de la mémoire et ne se bloque pas (Limité par la mémoire : Le CPU ne dépasse pas 50%
La lumière du disque n'est pas allumée, le programme va aussi vite qu'il peut, la boîte consomme 1.3G
de 2G de RAM). Donc, J'ai le choix entre être capable de reproduire le problème (mais pas d'en identifier la cause) ou être capable d'en identifier la cause ou un problème que je ne peux pas reproduire.
Mes meilleures suppositions actuelles quant à la prochaine étape sont :
- Obtenir une boîte follement grunty (pour remplacer la boîte de dev actuelle : 2Gb RAM dans un
E6550 Core2 Duo
) ; cela permettra de reproduire le comportement erroné à l'origine du crash lors de l'exécution dans un environnement de débogage puissant ; ou bien - Opérateurs de réécriture
new
ydelete
à utiliserVirtualAlloc
yVirtualProtect
pour marquer la mémoire comme étant en lecture seule dès qu'elle est utilisée. Exécuter sousMSVC6
et que le système d'exploitation attrape le méchant qui écrit dans la mémoire libérée. Oui, c'est un signe de désespoir : qui réécrit dans l'enfer ?new
ydelete
? ! Je me demande si cela va le rendre aussi lent que sous Purify et al.
Et, non : l'expédition avec l'instrumentation Purify intégrée n'est pas une option.
Un collègue vient de passer et demande "Stack Overflow ? On a des débordements de pile maintenant ? !?"
Et maintenant, la question : Comment localiser le corrupteur de tas ?
Mise à jour : équilibrage new[]
y delete[]
semble avoir fait un grand pas vers la résolution du problème. Au lieu de 15 minutes, l'application dure maintenant environ deux heures avant de planter. On n'en est pas encore là. D'autres suggestions ? La corruption du tas persiste.
Mise à jour : une version construite sous Visual Studio 2008 semble nettement meilleure ; les soupçons actuels reposent sur la STL
qui est livrée avec VS98
.
- Reproduisez le problème.
Dr Watson
produira un vidage qui pourrait être utile pour une analyse ultérieure.
J'en prends note, mais je crains que le Dr Watson ne soit pris au dépourvu qu'après coup, et non au moment où le tas de ferraille est piétiné.
Un autre essai pourrait être d'utiliser
WinDebug
comme outil de débogage, qui est assez puissant tout en étant léger.
J'ai ça en ce moment, encore une fois : pas très utile jusqu'à ce que quelque chose se passe mal. Je veux attraper le vandale sur le fait.
Peut-être ces outils vous permettront-ils au moins de circonscrire le problème à certains composants.
Je n'ai pas beaucoup d'espoir, mais les temps désespérés appellent...
Et êtes-vous sûr que tous les composants du projet ont des paramètres de bibliothèque d'exécution corrects (
C/C++ tab
(catégorie Génération de code dans les paramètres du projet VS 6.0) ?
Non, je ne le suis pas, et je passerai quelques heures demain à parcourir l'espace de travail (58 projets) et à vérifier qu'ils sont tous compilés et liés avec les drapeaux appropriés.
Mise à jour : Cela a pris 30 secondes. Sélectionnez tous les projets dans le Settings
désélectionnez jusqu'à ce que vous trouviez le ou les projets qui n'ont pas les bons paramètres (ils avaient tous les bons paramètres).