2010-02-12 5 views
1

Je continue d'obtenir une exception 'System.OutOfMemoryException' au niveau du code ci-dessous. Je ne peux pas savoir où la fuite de mémoire est et ce serait une aide précieuse si quelqu'un pouvait expliquer ce que je fais mal. Merci!Révision de code: problème OutOfMemoryException

lock ((_tabs)) 
{ 
    System.IO.StreamReader sr = null; 
    System.IO.MemoryStream ms = null; 
    try 
    { 
     Type[] t = { typeof(tsgPublicDecs.tsgClsTab) }; 
     System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t); 
     ms = new System.IO.MemoryStream(); 
     srl.Serialize(ms, _tabs); 
     ms.Seek(0, 0); 
     sr = new System.IO.StreamReader(ms); 
     return sr.ReadToEnd(); 
    } 
    finally 
    { 
     if (((sr != null))) 
     { 
      sr.Close(); 
      sr.Dispose(); 
     } 
     if (((ms != null))) 
     { 
      ms.Close(); 
      ms.Dispose(); 
     } 
    } 
} 

EDIT: Pour répondre à quelques-unes des questions:

  • _tabs n'est pas peuplé avec quelque chose (ce qui soulève beaucoup d'autres questions pour lesquelles son même être utilisé, mais je vais devoir demander au développeur qui l'a écrit pour cela)
  • La ligne qui lance l'erreur est 'srl.Serialize (ms, _tabs);'
  • Cette erreur est aléatoire et j'ai été incapable de la dupliquer moi-même mais en la laissant tourner pendant quelques jours, elle sera lancée. Pour cette raison, je suis incapable (je ne sais pas comment) d'obtenir des informations au-delà de l'erreur lancée.

EDIT 2: Merci pour toutes les entrées. L'ajout d'observations et la recherche d'autres fuites de mémoire possibles semblent être la meilleure approche. C'est génial de voir à quelle vitesse les gens peuvent donner un coup de main!

+0

Si vous utilisez "try", essayez {} catch (exception) {} finally {}. Autrement dit, vous avez raté la prise –

+0

Quelle est la taille de _tabs? –

+0

Quelle ligne lance l'exception? – FrustratedWithFormsDesigner

Répondre

0

Il crie pour un ou deux blocs.

lock ((_tabs)) 
{ 
     Type[] t = { typeof(tsgPublicDecs.tsgClsTab) }; 
     System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t); 

     using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) 
     { 
      srl.Serialize(ms, _tabs); 
      ms.Seek(0, 0); 

      using (System.IO.StreamReader sr = new System.IO.StreamReader(ms)) 
      { 
      return sr.ReadToEnd(); 
      } 
     } 


} 
+2

Ce code ne fonctionnera pas (ou ne compilera pas). A) vous n'avez pas besoin du bloc finally avec 'using', et B) vous utilisez le MemoryStream en dehors de sa portée. – ladenedge

+0

Ceci nécessite un bloc utilisant imbriqué. – kervin

+0

En outre, même si ce code a été correctement formé comme le mentionne kervin, il ne résoudrait toujours pas votre problème de manque de mémoire car il offre des ajustements purement syntaxiques. (Ce qui ne veut pas dire que l'utilisation de blocs ne sont pas des choses merveilleuses, bien sûr.) – ladenedge

0

Selon la taille de _tabs, le fait que vous lisez le flux sérialisé complet via sr.ReadToEnd() peut être à l'origine de cette erreur.

+0

stewsha a déclaré que l'exception revenait à la ligne Serialize(); la seule façon dont sr.ReadToEnd() le provoquerait est s'il appelait sr.ReadToEndAsync() –

0
  1. Comme d'autres l'ont dit, je suppose _tabs.

  2. Définir Visual Studio pour interrompre les exceptions levées et vérifier sa taille.

  3. Si vous allez simplement à Disposer, pourquoi ne pas utiliser des blocs 'using' imbriqués au lieu d'un bloc finally?

  4. Combien de threads s'exécutent lorsque vous obtenez l'exception de mémoire insuffisante? Votre bloc de code peut être suspendu à un moment où la mémoire a déjà été utilisée.

0

essayer ce .. Cela va dans SnippetCompiler. Si cela ne fonctionne pas pour vous, il existe une référence cyclique dans votre classe tsgClsTab. Et, oui, la recherche 'using' ;-)

using System; 
using System.Collections; 
using System.IO; 
using System.Xml.Serialization; 

public class MyClass 
{ 
    public static void RunSnippet() 
    { 
     var _tabs = new ArrayList(); 

     _tabs.Add(new tsgClsTab(1)); 
     _tabs.Add(new tsgClsTab(2)); 
     _tabs.Add(new tsgClsTab(3)); 
     _tabs.Add(new tsgClsTab(4)); 

     lock ((_tabs)) 
     { 
      StreamReader sr = null; 
      MemoryStream ms = null; 
      try 
      { 
       var srl = new XmlSerializer(typeof (ArrayList), 
              new Type[] {typeof (tsgClsTab)}); 
       ms = new MemoryStream(); 
       srl.Serialize(ms, _tabs); 
       ms.Seek(0, 0); 
       sr = new StreamReader(ms); 
       Console.WriteLine(sr.ReadToEnd()); 
      } 
      finally 
      { 
       if (((sr != null))) 
       { 
        sr.Close(); 
        sr.Dispose(); 
       } 
       if (((ms != null))) 
       { 
        ms.Close(); 
        ms.Dispose(); 
       } 
      } 
     } 
    } 

    #region Helper methods 

    public static void Main() 
    { 
     try 
     { 
      RunSnippet(); 
     } 
     catch (Exception e) 
     { 
      string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", 
             e.ToString()); 
      Console.WriteLine(error); 
     } 
     finally 
     { 
      Console.Write("Press any key to continue..."); 
      Console.ReadKey(); 
     } 
    } 

    #endregion 

    #region Nested type: tsgClsTab 

    public class tsgClsTab 
    { 
     public tsgClsTab() 
     { 
     } 

     public tsgClsTab(int id) 
     { 
      Id = id; 
     } 

     public int Id { get; set; } 
    } 

    #endregion 
} 

SORTIE

<?xml version="1.0"?> 
<ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <anyType xsi:type="tsgClsTab"> 
    <Id>1</Id> 
    </anyType> 
    <anyType xsi:type="tsgClsTab"> 
    <Id>2</Id> 
    </anyType> 
    <anyType xsi:type="tsgClsTab"> 
    <Id>3</Id> 
    </anyType> 
    <anyType xsi:type="tsgClsTab"> 
    <Id>4</Id> 
    </anyType> 
</ArrayOfAnyType> 
3

Etes-vous sûr que le problème est ici?

Ne fuyez-vous pas la mémoire ailleurs? OutOfMemoryException peut être lancé sur l'allocation de mémoire de n'importe où, et il peut être juste une coïncidence que cela se soit passé ici.Essayez de profiler l'application dans un profileur de mémoire pour voir si vous détenez des références qui provoqueront une fuite de votre mémoire. Essayez de retirer autant de RAM que possible de votre machine de test (en fonction du système d'exploitation, essayez de passer à 256/128 Mo sur XP) et exécutez des cas d'utilisation répétitifs plusieurs fois (pas nécessairement seulement le cas d'utilisation qui fonctionne). ce code).

0

Voici une autre suggestion, si vous pouvez le balancer. Remplacer _tabs 'déclaration (que je suppose est déclarée comme ArrayList somwhere) avec un fortement typé générique en tant que tel:

ancienne: private ArrayList _tabs = new ArrayList(); nouveau: private List<tsgPublicDecs.tsgClsTab> _tabs = new List<tsgPublicDecs.tsgClsTab>();

Et régler la XmlSerializer instanciation de la même. Cela étant dit, après quelques tests assez basiques, je n'ai pu obtenir aucune exception de MOO. Voici ce que les autres ont dit que la simplification avec usings:

lock (_tabs) 
    { 
     Type[] t = { typeof(tsgPublicDecs.tsgClsTab) }; 
     System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t); 
     using (System.IO.Stream ms = new System.IO.MemoryStream()) 
     { 
      srl.Serialize(ms, _tabs); 
      ms.Seek(0, 0); 
      using (System.IO.TextReader sr = new System.IO.StreamReader(ms)) 
      { 
       return sr.ReadToEnd(); 
      } 
     } 
    } 

EDIT: bien devinez quoi? J'étais capable de faire une exception OutOfMemoryException. Mais seulement avec un arraylist de 10.000 de ces articles, chacun ayant une référence à la précédente. Il s'agit donc d'un graphe d'objets assez compliqué quand il s'agit d'en arriver là et c'est peut-être ce que vous rencontrez.

Questions connexes