Question

Je vais avoir des problèmes avec une fuite de mémoire lente dans mon mode mixte C ++ / CLR application .NET.

(il est C ++ bibliothèques statiques natives reliées dans un VS2008 C ++ / CLR Windows Forms application avec le paramètre du compilateur "/ clr")

Comportement typique: l'application commence à utiliser 30 Mo (mémoire privée). fuites alors la mémoire slowish, dire Mo toutes les heures lors de l'exécution sous une charge simulée lourde. Ceci simule l'application étant en direct pendant des jours ou des semaines.

Je l'ai essayé d'utiliser plusieurs outils pour traquer les fuites de mémoire, y compris à la fois le genre d'outils CRT qui vient avec les libs CRT Visual Studio. Je l'ai aussi utilisé un outil de détection des fuites du commerce ( « Memory Validator »).

Les deux rapports fuites de mémoire négligeable à l'arrêt (quelques entrées mineures ce montant à quelques KB que je ne suis pas inquiet). De plus, je peux voir lors de l'exécution que la mémoire ne chenillé (je ne crois pas qu'il est juste mémoire qui est détenu et seulement libéré à la sortie de l'application) semble ne pas représenter beaucoup. Je reçois environ 5 Mo de mémoire énumérés (sur un total> 30 Mo).

L'outil (Memory Validator) est configuré pour suivre toute l'utilisation de la mémoire (y compris malloc, nouvelle, allocation de mémoire virtuelle et tout un tas d'autres types d'allocation de mémoire). Fondamentalement, chaque paramètre pour lequel la mémoire à la piste a été sélectionnée.

L'image .NET signale qu'il utilise environ 1,5 Mo de mémoire (perfmon).

Voici un dernier bit d'information: nous avons une version de l'application qui fonctionne comme une application native de la console (purement native - pas du tout CLR). Ceci est 95% identique au mode mixte, sauf sans la substance de l'interface utilisateur. Cela ne semble pas une fuite de mémoire du tout, et des pics à environ 5MB octets privés.

Donc, fondamentalement, ce que je suis en train de se passer ici est que je ne pense pas que le code natif est une fuite de mémoire.

Une autre pièce du puzzle: je l'ai trouvé ce qui fait référence à des fuites de mémoire dans les applications en mode mixte lors du ciblage 2.0 cadre (que je suis): http://support.microsoft.com/kb/961870

Malheureusement, les détails sont rares exaspérante donc je ne sais pas si elle est pertinente. J'ai essayé le ciblage 3,5 au lieu de 2,0 cadre mais toujours eu le même problème (peut-être que je ne l'ai pas ce droit).

Quelqu'un a des suggestions?

Quelques choses qui pourraient me aider:

  • Y at-il un autre type d'allocations de mémoire que je ne suis pas suivi?
  • Comment se fait les chiffres ne concordent pas? Je reçois 5 Mo d'utilisation de la mémoire CRT, 1,5 Mo de mémoire .NET alors comment l'application se ensemble utilise octets privés de 30MB? Est-ce que tous ligotés dans le cadre de .NET? Pourquoi ne vois-je pas ces derniers dans l'outil de fuite? N'apparaîtra pas le framework .NET comme une sorte de mémoire allouée?
  • Les autres outils de détection des fuites qui fonctionnent bien avec des applications en mode mixte?

Merci pour toute aide

John

Était-ce utile?

La solution

OK j'ai finalement trouvé le problème.

Il a été causé par un mauvais réglage pour / EH (Manipulation des exceptions).

En fait, avec des applications .NET en mode mixte, vous devez vous assurer que tous les libs liés statiquement sont compilées avec / EHa au lieu de la valeur par défaut / EHs.

(L'application elle-même doit également être compilée avec / EHa, mais cela est une donnée -.. Le compilateur signale une erreur si vous ne l'utilisez pas Le problème est lorsque vous liez dans d'autres bibliothèques natives statiques)

Le problème est que les exceptions pris dans le bit géré de l'application, qui ont été jetés dans les bibliothèques natives compilées avec / EHs finissent par la manipulation non l'exception correctement. Destructeurs pour les objets de C ne sont pas alors appelés correctement.

Dans mon cas, cela ne se produisait que dans un lieu rare, d'où la raison pour laquelle il m'a fallu les âges à repérer.

Autres conseils

Comme Spence a été dit, mais pour C ++ / CLI;) ....

Pour tout objet que vous utilisez en C ++ / CLI, si vous créez plus cet objet de de votre code C ++, vous devriez essayer d'utiliser seymantics d'allocation de la pile, même si cela est un compilateur genre magique de chose, il est en mesure de configurer le __try imbriqué {} {} __finally déclarations que vous pouvez être habitué à l'utilisation du code natif (qui les configurer de manière à ne pas perdre un appel à Éliminez).

Nish article au projet de code sur C ++ / CLI sémantique d'allocation de la pile est assez bonne et passe en profondeur sur la façon d'imiter en utilisant {}.

Vous devez également vous assurer de supprimer cette implment IDisposable de tout objet que vous ne pouvez pas appeler en Éliminez C ++ / CLI, supprimez le fait pour vous, si vous n'êtes pas en utilisant la sémantique de la pile ..

J'appelle habituellement près moi-même sur les ruisseaux et essayer d'assigner nullptr quand je suis fini avec son objet, juste au cas où.

Vous pouvez également consulter cet article sur les problèmes de mémoire , perticularly des abonnés d'un événement, si vous attribuez à vos objets de l'événement, vous pouvez ... une fuite de

En dernier recours (ou peut-être d'abord :), une chose que je l'ai fait dans le passé est d'utiliser l'API profileur CLR, voici un autre article sur la façon de le faire, l'auteur de l'auteur (Jay Hilyard) a un exemple qui répond;

  • de chaque type .NET qui est utilisé, comment plusieurs instances d'objets sont en cours alloué?
  • Quelle sont les instances de chaque type?
  • Quelles notifications ce que le GC fournit comme il va à travers une collecte des ordures et ce pouvez-vous trouver?
  • Quand le GC recueillir les instances d'objet?

Si vous obtenez une meilleure idée que certains profileur des produits de base, je l'ai remarqué qu'ils peuvent parfois être trompeuses en fonction de votre allocation porofile (BTW. Attention pour les problèmes grands tas d'objets,> ~ objets 83kb sont spécialement traités, en ce sens cas, je reccomend, sortir du tas d'objets volumineux.)

Compte tenu de vos commentaires, quelques choses ...

Je l'ai posté avant au sujet de quota de ne pas faire payer la charge de l'image ou toute autre statistique disernable, ce que cela signifie, vous devrez peut-être retrouver un certain problème de poignée ou d'un chargeur (voir verrouillage du chargeur éventuellement), mais avant cela, vous pouvez essayer de régler un peu de régions d'exécution avec contraintes , ils peuvent travailler des merveilles, mais sont aussi malheureusement difficiles à rétrofit en code non pur.

Cette récente MSDN Mag , document de l'article est beaucoup de perfmon sperlunking de mémoire de type ( cet aîné ).

De VS Blog Perf, ils montrent comment utiliser SOS en studio visuel, qui peut être à portée de main, pour traquer rouge DLL, les commentaires sont aussi bons.

Blog Maoni Stephen et Rick Byers est un dev avec l'équipe de diagnostic CLR, beaucoup de son blog -buddies sont égalementbien que je conseillerais fortement cependant de la source, aussi référant au tout nouveau forum dev / diagnostic . Ils ont récemment élargi le champ de leurs discussions.

Outils de couverture de code et cette l'entreprise, est tout à fait bon, il est capable de dériver les fuites natives / gérées de traces à partir de son profil, vous apporte Retour aux lignes exactes de la source (même si optimisé, très agréable (et il a un essai 30 jours)))).

Bonne chance !! Espérons que certaines de cette aide, il est seulement frais dans mon esprit, comme je le fais beaucoup de travail en ce moment même;)

Essayez: DebugDiags .
Après avoir généré une mémoire décharges, il vous donnera une belle estivale de ce que la mémoire a été alloué, et en fonction de votre recherche PDB de, il peut vous dire par qui il a été attribué.

Vous pouvez avoir une fuite de référence, regardez dans ANTS logiciel de profilage. Ants Profiler

Une fuite de référence est l'équivalent .net d'une fuite de mémoire, vous tenez des références à un objet qui arrête étant les ordures collectées, et donc vous la mémoire en cours d'utilisation commence à monter.

Est-il possible que vous avez manqué quelques éliminateurs, peut se produire si vous utilisez GDI + et bien d'autres API.

Si votre exécutez l'outil d'analyse statique FXCop il a une règle pour vérifier si vous avez appelé Éliminez (ou utilisé les « utilisant ») des déclarations sur vos objets qui fournissent l'interface. Dans .Net si une fonction utilise le code non géré, il fournira généralement une méthode ou Éliminez proche pour vous de ne fuira pas la ressource / mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top