2009-02-14 5 views
11

Grâce à ma collection crash automatisé pour MaxTo je suis arrivé le rapport d'accident suivant:Win32Exception Pas assez de stockage est disponible pour traiter cette commande

V8.12.0.0 - System.ComponentModel.Win32Exception - :Void UpdateLayered():0 
Version: MaxTo8.12.0.0 
Exception: System.ComponentModel.Win32Exception 
Error message: Not enough storage is available to process this command 
Stack trace: 
    at System.Windows.Forms.Form.UpdateLayered() 
    at System.Windows.Forms.Form.OnHandleCreated(EventArgs e) 
    at System.Windows.Forms.Control.WmCreate(Message& m) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ScrollableControl.WndProc(Message& m) 
    at System.Windows.Forms.ContainerControl.WndProc(Message& m) 
    at System.Windows.Forms.Form.WmCreate(Message& m) 
    at System.Windows.Forms.Form.WndProc(Message& m) 
    at MaxTo.MainForm.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

Une autre stacktrace:

Version: MaxTo2009.9.0.0 
Exception: System.ComponentModel.Win32Exception 
Error message: Not enough storage is available to process this command 
Stack trace: 
    at System.Windows.Forms.Form.UpdateLayered() 
    at System.Windows.Forms.Form.OnHandleCreated(EventArgs e) 
    at System.Windows.Forms.Control.WmCreate(Message& m) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.ScrollableControl.WndProc(Message& m) 
    at System.Windows.Forms.ContainerControl.WndProc(Message& m) 
    at System.Windows.Forms.Form.WmCreate(Message& m) 
    at System.Windows.Forms.Form.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

Dans cette dernière trace de la pile, il n'est pas du tout une référence à MaxTo, et 90% des plantages que je reçois sont avec des traces de pile similaires à celles ci-dessus. Lecture sur le net Je trouve que cette erreur est habituelle si vous oubliez de libérer ou de disposer des variables. Lorsque je regarde à travers mon WndProc, qui semble parfois avoir le problème passer, je ne peux pas trouver un seul endroit qui se accroche à des références à des objets. Toutes les variables, sauf une, sont locales à WndProc et doivent donc être collectées lorsque la méthode se termine.

protected override void WndProc(ref Message m) 
{ 
    base.WndProc(ref m); // I'm assuming the first trace can be caught here 
    IntPtr hwnd = m.WParam; 
    // Our hook tells us something got maximized 
    if (Win32Import.UWM_MAXIMIZE == (UInt32)m.Msg) 
    { 
     // Figure out if we are temporarily disabled or using alternative profiles 
     KeyStateInfo keyState = KeyboardInfo.GetKeyState(Settings.AlternativeProfileKey); 
     Rectangle r = FindRectangle(MousePosition, (Settings.EnableAlternativeProfile && keyState.IsPressed ? AlternativeRegions : Regions)); 
     // Did we find a rectangle to place it in? 
     if (r != Rectangle.Empty) 
     { 
      Rectangle position = Win32Import.GetWindowRectangle(hwnd); 
      Rectangle previousPos = GetLocation(hwnd); 
      if (position == r && previousPos != Rectangle.Empty) 
      { 
       // We are restoring the original position 
       Win32Import.SetWindowPos(hwnd, IntPtr.Zero, previousPos.X, previousPos.Y, previousPos.Width, previousPos.Height, Win32Import.SWP_NOZORDER | Win32Import.SWP_NOSENDCHANGING); 
      } 
      else 
      { 
       // We are maximizing to a region 
       Win32Import.ShowWindow(hwnd, Win32Import.WindowShowStyle.Restore); 
       Win32Import.SetWindowPos(hwnd, IntPtr.Zero, r.X, r.Y, r.Width, r.Height, Win32Import.SWP_NOZORDER | Win32Import.SWP_NOSENDCHANGING); 
       // Make sure we remember this location 
       RememberLocation(hwnd, position); 
      } 
     } 
    } 
    else if (MaxTo64WindowHandleMessage == m.Msg) 
    { 
     // Store the window handle of our 64-bit subprocess 
     SubProcess64WindowHandle = m.WParam; 
    } 
} 

Je n'ai pas réussi à reproduire l'erreur, même si vous avez exécuté le programme sur plusieurs jours. Mon hypothèse est que le système est faible sur la mémoire non fragmentée ou les poignées GDI, mais je ne peux pas le confirmer où que ce soit. Il ne semble pas y avoir de bonne documentation sur cette erreur.

Des idées quoi d'autre pourrait-il être? Puis-je faire quelque chose pour éviter cette erreur?

Mise à jour: La question a été rouverte avec plus de traces de pile, en raison de l'absence d'une solution décente. Le fait de l'ignorer ne résout pas le problème.

+0

Non lié à la question mais comment collectez-vous les rapports d'accident? – Giorgi

+0

Utilisation de Fogbugz BugzScout (Google it) et d'un gestionnaire d'erreurs global personnalisé dans le programme. Ce n'est pas trop dur. –

+0

Est-ce que quelque chose est signalé dans le journal des événements de l'application Windows au moment de l'erreur? –

Répondre

11

Fuite ou utilisation de nombreux objets/poignées GDI. Ceux-ci pourraient causer une pénurie de tas de ressources. Vous ne pourrez peut-être pas reproduire car vos utilisateurs peuvent avoir d'autres programmes lourds de ressources GDI en cours d'exécution ou utiliser Terminal Server, auquel cas ils doivent partager une partie du tas avec les autres utilisateurs. Voir System Error. Code: 8. Not enough storage is available to process this command

Here Vous pouvez consulter l'outil Desktop Heap Monitor pour diagnostiquer les problèmes de tas de bureau.

Here et here et here sont des outils de détection de fuite GDI.

+0

Ça doit être ça. Je suppose que cet accident a été provoqué par d'autres programmes qui ont fui les poignées du GDI. Surveiller mon programme a montré qu'il n'y a pas de fuite là-bas. –

+0

Avez-vous essayé d'augmenter le tas de bureau? Mon expérience est que cette erreur se produit plus souvent sur les systèmes Terminal Server où des parties du tas de bureau sont partagées entre les utilisateurs. Cela pourrait expliquer pourquoi cette erreur se produit plus souvent dans ces cas. –

+0

Le problème est qu'il n'a jamais été reproductible sur aucun de mes ordinateurs, donc je n'ai rien à reproduire. J'ajoute plus de collecte de données à l'analyse de l'accident, mais il me faudra beaucoup de temps avant d'avoir des données plus détaillées. –

5

Votre programme fuit probablement les ressources du noyau. Commencez à diagnostiquer ce problème avec Taskmgr.exe. Afficher + Sélectionner les colonnes, vérifier les objets Utilisateur, les objets GDI et le nombre de poignées. Exécutez votre programme et observez si l'un de ceux-ci augmente régulièrement. Une fois que l'un d'entre eux atteint 10 000, votre programme va mourir.

Avec un moyen de voir rapidement la fuite en action, vous pouvez commencer à commenter le code pour voir où la fuite se produit. Cela a probablement quelque chose à voir avec votre "crochet".

1

Le problème ne réside probablement pas dans votre WndProc - la raison pour laquelle vous le voyez dans vos piles d'appels est que tout ce qui est lié à l'interface graphique sous Windows passe par la procédure de la fenêtre WIN32. Le remplacer par votre contrôle vous donne simplement un point d'ancrage pour traiter des choses de bas niveau avant que le traitement de l'infrastructure .NET de haut niveau ne soit effectué.

Ceci va être un complet tourné dans l'obscurité, mais peut-être this post pourrait être pertinent? - probablement pas avec ces traces de pile, cependant.

+0

Je ne vois pas comment cela serait pertinent, car je ne vois pas le message que vous avez lié à cette erreur Cependant, la fenêtre principale de MaxTo a des panneaux imbriqués, mais pas à des profondeurs de 12 à 15, à moins que l'utilisateur ne devienne vraiment bizarre avec ses paramètres. :) –

+0

@Vegard: les traces de la pile seraient probablement différentes si c'était le problème. Est-il possible d'obtenir des traces de pile Win32 complètes et pas seulement la trace .net? – snemarch

+0

Je ne pense pas si facilement. Je n'ai jamais été capable de reproduire sur mes propres machines. La trace de pile est simplement à partir de l'objet Exception, je n'ai pas idée comment obtenir la piletrace Win32 (et je devrais fournir à l'utilisateur une construction personnalisée après avoir trouvé comment l'obtenir à partir de .NET). –

0

J'avais de nombreux contrôles Windows personnalisés avec des ressources propres, donc quand je crée beaucoup de contrôles, cette erreur apparaît. Pour résoudre ce problème j'ai fait le fichier de ressources dans ma bibliothèque et utilisé des ressources extérieures au lieu de ressources sur mon code de composant. Après que mon exception est parti, déjà testé avec 3 fois plus de formulaires ouverts et cette erreur disparue. On dirait que c'est une solution.

Questions connexes