txt net manejo leer fichero escribir crear asp archivos archivo abrir c# .net xna garbage-collection

manejo - leer archivo txt asp net c#



Crear y escribir un archivo XML arroja la excepción-> sistema de memoria fuera de la excepción? (6)

¿Qué tan grande es widthNode, lengthNode y heightNode en su código de carga? Si llega algún valor irrazonable, podría terminar asignando una gran matriz de acceso - y se asignarán objetos lo suficientemente grandes en el gran montón de objetos, que es mucho más difícil de gestionar - por un lado, no se compacta. Entonces tendrías un proceso de 3 GB que solo usa 70 MB de memoria.

¿La excepción ocurre en la carga repetida (y la liberación), o también ocurre si carga solo un nodo por cada aplicación que se ejecuta? Los objetos por vista de dirección en el perfilador CLR son útiles para tener en cuenta la disposición de la memoria real: verá lagunas de espacio libre con bastante facilidad si su problema es la fragmentación del montón.

Y por último, pero no menos importante, es posible que OutOfMemoryException esté completamente equivocado por alguna razón: el culpable habitual tiende a obtener un valor incorrecto en los constructores de matrices (por ejemplo, la nueva int [int.MaxValue] va a fallar).

He estado desarrollando durante algún tiempo un pequeño juego llamado ''voxel'' en XNA. Un .NET C # como el juego Minecraft. Utilizo un concepto simple para guardar y leer datos de mis juegos para construir el mapa mundial. Todo está almacenado en un archivo xml.

Ahora intento cargar un mapa más grande, y ''paf'' se genera una excepción durante la generación de mi mapa:

[ Sistema sin memoria de excepción ]

No entiendo por qué, porque después de la excepción, mi archivo no es muy pesado, es de unos 70 mb . ¿Es normal ver un aumento de excepción durante la generación de un archivo XML de hasta 70 mb ?

Entorno de desarrollo utilizado

  • Microsoft Windows 7 (x64) bits
  • Visual Studio 2012 professionnel Actualización 3
  • 8192 Ram
  • CPU Intel i5 2.5 Ghz (4 cpus)

Hice una prueba con CLR Profiler para comprobar cómo funciona el recolector de basura:

El código donde inicializo mi XmlWritter:

private XmlTextWriter myXmlTextWriter ; #region prepareNewWorldXmlFIle private void PreparedNewWorldXmlFile() { Stream fs = new FileStream(currentPath + "World//world.xml", FileMode.Create); myXmlTextWriter = new XmlTextWriter(fs,Encoding.ASCII); myXmlTextWriter.Formatting = Formatting.Indented; myXmlTextWriter.WriteStartDocument(false); myXmlTextWriter.WriteComment("World Map ID:"); //World and his attribute myXmlTextWriter.WriteStartElement("World"); myXmlTextWriter.WriteStartElement("Matrix", null); myXmlTextWriter.WriteStartElement("Regions"); } #endregion

El código que uso para generar mi mapa mundial y escribir un archivo xml:

//Octree calcul and generate map to xml file foreach (Region region in arcadia.world.Regions) { isAllCheckSameIdOctree = false; if (isFirstGenerationWorld) { //Regions and attributes myXmlTextWriter.WriteStartElement("Region"); myXmlTextWriter.WriteAttributeString("id", indexRegion.ToString()); myXmlTextWriter.WriteAttributeString("min", "x:" + region.PositionMin.X + ";y:" + region.PositionMin.Y + ";z:" + region.PositionMin.Z); myXmlTextWriter.WriteAttributeString("max", "x:" + region.PositionMax.X + ";y:" + region.PositionMax.Y + ";z:" + region.PositionMax.Z); myXmlTextWriter.WriteStartElement("Structures"); myXmlTextWriter.WriteAttributeString("type", "cube"); } indexRegion++; if (region.Matrice != null) { //If the node to generate contain minimum a height divisible by 2 if (((region.PositionMax.Y - region.PositionMin.Y) / 2) > 2) { //generate and octree by 8 GenerateNodes(region, region.PositionMin, 8); } else if (((region.PositionMax.Y - region.PositionMin.Y) / 2) <= 2) { //generate and octree by 4 GenerateNodes(region, region.PositionMin, 4); } while (!isAllCheckSameIdOctree) { if (nodeToRegenerate != null && needRecurseBuild) { //if the node is greater than 2 if (nodeToRegenerate.TotalHeight > 2) { nodeToRegenerate = GenerateNodes(nodeToRegenerate, region, nodeToRegenerate.Position, 8); if (nodeToRegenerate == null) { isAllCheckSameIdOctree = true; } } else if (nodeToRegenerate.TotalHeight <= 2) { nodeToRegenerate = GenerateNodes(nodeToRegenerate, region, nodeToRegenerate.Position, 4); if (nodeToRegenerate == null) { isAllCheckSameIdOctree = true; } } } else { isAllCheckSameIdOctree = true; } } if (isFirstGenerationWorld) { myXmlTextWriter.WriteEndElement();//Ferme le noeud Structures myXmlTextWriter.WriteEndElement();//Ferme le noeud Region myXmlTextWriter.Flush(); } } else { if (isFirstGenerationWorld) { myXmlTextWriter.WriteEndElement();//Ferme le noeud Structures myXmlTextWriter.WriteEndElement();//Ferme le noeud Region myXmlTextWriter.Flush(); } } } if (isFirstGenerationWorld) { myXmlTextWriter.WriteEndElement();//Ferme le noeud Regions myXmlTextWriter.WriteEndElement();//Ferme le noeud World myXmlTextWriter.Flush(); myXmlTextWriter.Close(); }

Captura de excepciones en mi función generatedNode, ver más abajo para más información

Mi función generatedNode recursive donde la excepción se dispara con ''system out of memory exception

#region ReGenerateWorld private Node GenerateNodes(Node nodeToRegenerate, Region region, Vector3 position, int countToCut) { //Relative dimension of the parent octree int widthParent = (int)nodeToRegenerate.TotalWidth / 2; int heightParent = (int)nodeToRegenerate.TotalHeight / 2; int lenghtParent = (int)nodeToRegenerate.TotalLenght / 2; //Relative dimension of the parent octree int widthNode = (widthParent) / (countToCut / (countToCut / 2)); int heightNode = (heightParent) / (countToCut / (countToCut / 2)); int lenghtNode = (lenghtParent) / (countToCut / (countToCut / 2)); if (heightNode < 1) { heightNode = 1; } int refX = (int)position.X / 2; int refY = (int)position.Y / 2; int refZ = (int)position.Z / 2; int indexStartX = 0; int indexStartY = 0; int indexStartZ = 0; int nbrToCut = 0; if (heightParent >= 2) { nbrToCut = ((widthParent / (widthParent / 2))) * ((heightParent / (heightParent / 2))) * ((lenghtParent / (lenghtParent / 2))); } else { nbrToCut = 4; heightNode = 1; } //Calculate the number of cubic to cut //Génére les noeud racine int countVertical = 0; int calcPosX = 0; int calcPosY = 0; int calcPosZ = 0; int[][][] nodeMatriceWorld = null; bool firstTime; newNode = null; int idGroup = 0; bool isSameId = true; int idToCheck = 0; for (int index = 0; (index < nbrToCut) && (refY < 32); index++) { indexStartX = refX; indexStartY = refY; indexStartZ = refZ; try { nodeMatriceWorld = new int[widthNode][][]; for (int i = 0; i < widthNode; i++) { nodeMatriceWorld[i] = new int[lenghtNode][]; for (int j = 0; j < lenghtNode; j++) { nodeMatriceWorld[i][j] = new int[heightNode]; } } } catch (Exception ex) { // OUT OF MEMORY EXCEPTION HERE Console.Out.WriteLine(ex.Message); } firstTime = true; for (int epaisseur = 0; epaisseur < heightNode; epaisseur++, indexStartY++) { for (int ligne = 0; ligne < lenghtNode; ligne++, indexStartZ++) { for (int collone = 0; collone < widthNode; collone++, indexStartX++) { if (firstTime) { calcPosX = indexStartX; calcPosY = indexStartY; calcPosZ = indexStartZ; firstTime = false; } nodeMatriceWorld[collone][ligne][epaisseur] = matriceWorld[indexStartX][indexStartZ][indexStartY]; } indexStartX = refX; } indexStartZ = refZ; } indexStartY = refY; idGroup = matriceWorld[calcPosX][calcPosZ][calcPosY]; countVertical++; if (newNode != null) { newNode.Dispose(); } newNode = new Node(nodeMatriceWorld, new Vector3(calcPosX, calcPosY, calcPosZ), idGroup, widthNode, heightNode, lenghtNode); region.Nodes[idGroup].Add(newNode); //Regions.Add(new Node(nodeMatriceWorld, new Vector3(calcPosX, calcPosY, calcPosZ), idGroup)); refX += widthNode; if (countVertical >= 4) { refY = ((int)position.Y / 2) + heightNode; refX = ((int)position.X / 2); refZ = (int)position.Z / 2; countVertical = 0; } else if (countVertical == 2) { refZ = ((int)position.Z / 2) + lenghtNode; refX = ((int)position.X / 2); } } isSameId = true; nodeToRegenerate = null; needRecurseBuild = false; idToCheck = 0; // Check for each octree node if all are the same id foreach (List<Node> listNode in region.Nodes) { foreach (Node node in listNode.Where(m => m.isGroupSameId == false)) { isSameId = true; idToCheck = node.matriceNode[0][0][0]; node.isGroupSameId = true;//Le met a true au depart for (int epaisseur = 0; epaisseur < node.TotalHeight / 2 && isSameId; epaisseur++) { for (int ligne = 0; ligne < node.TotalLenght / 2 && isSameId; ligne++) { for (int collone = 0; collone < node.TotalWidth / 2 && isSameId; collone++) { if (node.matriceNode[collone][ligne][epaisseur] != idToCheck) { isSameId = false;//si au moin un cube est différent on le marque node.isGroupSameId = false; //node.ItemGroup = node.matriceNode[collone, epaisseur, ligne]; nodeToRegenerate = node; needRecurseBuild = true; break; } } } } if (!isSameId) { break; } else { if (idToCheck != 0) { isSameId = true; node.isGroupSameId = true; node.ItemGroup = idToCheck; node.matriceNode = null; node.Cube = new Primitives3D.Cube(node.ItemGroup, node.Position, new Vector3(0, 0, 0), node.TotalWidth, node.TotalHeight, node.TotalLenght); //Initialise le cube qui représente le noeud node.Cube.BuildCubeStart(); if (isFirstGenerationWorld) { myXmlTextWriter.WriteStartElement("Cube"); //Structures et ses attributs myXmlTextWriter.WriteAttributeString("id", node.ItemGroup.ToString()); myXmlTextWriter.WriteAttributeString("min", "x:" + node.Cube.BoundingBox.Min.X + ";y:" + node.Cube.BoundingBox.Min.Y + ";z:" + node.Cube.BoundingBox.Min.Z); myXmlTextWriter.WriteAttributeString("max", "x:" + node.Cube.BoundingBox.Max.X + ";y:" + node.Cube.BoundingBox.Max.Y + ";z:" + node.Cube.BoundingBox.Max.Z); myXmlTextWriter.WriteEndElement();//Ferme le noeud xml cube myXmlTextWriter.Flush(); } //Ajoute l''id du noeud aux groupe d''id de la region s''il n''y était pas auparavant if (!region.IdFound.Contains(node.ItemGroup) && node.ItemGroup != 0) { region.IdFound.Add(node.ItemGroup); } } // If the node group is equal to an empty group id -> 0 it removes entire else { nodeToDelete = node; } } } if (!isSameId) { break; } //Console.Out.WriteLine("Nodes cout generated : " + Nodes.Count.ToString()); } // If a node does not contain all the same id -> go remove it if (!isSameId) { region.Nodes[nodeToRegenerate.ItemGroup].Remove(nodeToRegenerate); } if (nodeToDelete != null) { region.Nodes[nodeToDelete.ItemGroup].Remove(nodeToDelete); } nodeToDelete = null; //Dispose the resources newNode.Dispose(); nodeMatriceWorld = null; return nodeToRegenerate; } #endregion

La excepción:


En primer lugar, asegúrese de cerrar FileStream después de usarlo. ejemplo) - esta es una de las mejores prácticas.

private void PreparedNewWorldXmlFile() { using(Stream fs = new FileStream(currentPath + "World//world.xml", FileMode.Create)) { myXmlTextWriter = new XmlTextWriter(fs,Encoding.ASCII); myXmlTextWriter.Formatting = Formatting.Indented; myXmlTextWriter.WriteStartDocument(false); myXmlTextWriter.WriteComment("World Map ID:"); //World and his attribute myXmlTextWriter.WriteStartElement("World"); myXmlTextWriter.WriteStartElement("Matrix", null); myXmlTextWriter.WriteStartElement("Regions"); } }

Creo que deberías liberar todos los objetos de nodo en tu instancia de clase de región. porque GC no recopilará la instancia de clase de región, sin embargo, la configura como nula.


Hace poco recibí un error similar al procesar XML a través de XSLT. Mis archivos eran solo 5MB sin embargo. Cambié mi procesamiento XSLT a una clase .net (conversión usando la herramienta de conversión MS) y eso resolvió el problema. Aparentemente algunos errores con el procesador XSLT.

Es posible que tenga un problema similar y, tal como lo sugiere el otro usuario, intente utilizar diferentes procesadores de documentos XML, ya que el usuario puede tener un error o una limitación.


Puede salirse de la excepción de memoria con métodos recursivos cuando se queda sin memoria de pila. Básicamente, su recursión es infinita o cercana a ella lo suficiente como para agotar la memoria reservada para la pila.


Según tengo entendido, tu problema no está en XML, sino en la matriz dentada int [] [] [] nodeMatriceWorld . Su tamaño es demasiado grande o está creando esta matriz demasiadas veces. Aquí está tu código:

try { nodeMatriceWorld = new int[widthNode][][]; for (int i = 0; i < widthNode; i++) { nodeMatriceWorld[i] = new int[lenghtNode][]; for (int j = 0; j < lenghtNode; j++) { nodeMatriceWorld[i][j] = new int[heightNode]; } } } catch (Exception ex) { // OUT OF MEMORY EXCEPTION HERE Console.Out.WriteLine(ex.Message); }

Compruebe widthNode, lenghtNode y heightNode. Para nodeMatriceWorld necesita al menos sizeof (int) * widthNode * lenghtNode * heightNode bytes de memoria.


parece que intentas representar un mapa con una matriz tridimensional, usando un mapa de alturas; sin embargo, solo necesitas 2 dimensiones.

ejemplo: la matriz: int map [x] [y]; donde el valor del mapa [x] [y] es la z.

de esta manera necesitas mucha menos memoria que debería arreglar tu problema