2009-05-26 9 views
7

Necesito crear una gran lista de cadenas y mantenerla en la memoria, sin embargo, al generarla, se lanza una OutOfMemoryException. De acuerdo con Resource Monitor, todavía tengo 1GB de memoria disponible. Encontré this KB article abordando el problema, pero parece que debería haber sido reparado en el framework 1.1 SP1 (estoy usando 3.5 sp1).OutOfMemoryException lanzada mientras la memoria aún está disponible

¿Alguien puede arrojar algo de luz sobre lo que sucede detrás de escena? ¿El marco .net limita la cantidad de memoria que puede ser utilizada por un único proceso (en un sistema de 32 bits)? Si es así, puedo ver por qué, pero lo que no tiene sentido es que la aplicación solo está usando 1.6 GB y aún le quedan ~ 1GB al sistema.

Editar - Para los que pidió que aquí hay alguna información más en profundidad:

Tengo una lista (Sí, podría utilizar algo más, pero sólo estoy de prototipos en este momento.), Genero una cadena aleatoria haciendo un Guid.NewGuid(). ToString(), y tírelo a la lista. Lo que intento hacer es generar una lista con tantos elementos como pueda, y probar diferentes métodos para buscar uno específico. Mi primera suposición fue que algo de fragmentación está ocurriendo, pero dejé todo excepto el código a continuación, y todavía sucede. No creo que este pequeño fragmento pueda crear mucha fragmentación, pero probablemente estoy equivocado.

 List<string> blah = new List<string>(); 

     for (int i = 0; i < 50000000; i++) 
     { 
      blah.Add(Guid.NewGuid().ToString()); 
     } 
+0

¿Puede proporcionar un fragmento de código de dónde está llegando a OutOfMemoryException? –

+0

¿Qué estructura de datos estás usando? ¿Lista ? – RichardOD

Respuesta

9

El problema no es probable que usted no tiene la memoria "disponible", pero es más probable que usted tiene fragmentó la memoria tanto que cuando intentas agregar un elemento a la lista, y debe ser redimensionado, ningún bloque individual de memoria disponible puede contenerlo.

Esto también dará lugar a OutOfMemoryException.

¿Qué tan grande es la lista, en otras palabras, cuántas cadenas tiene, exactamente o más o menos, cuando obtiene la excepción?

¿Y cómo está rellenando la lista? ¿Sabe de antemano la cantidad de elementos que va a agregar? Y si es así, ¿especificas la capacidad cuando construyes la lista?

Si no lo sabe, ¿sería posible averiguarlo, por lo que podría especificar esa capacidad?

+0

Especificando el tamaño de la lista, ¡gracias! – Joe

0

Realmente no sé los detalles de este error, pero me encuentro con esto, o algo muy parecido, hace años. Esencial, encontramos que había un límite estricto en la cantidad de identificadores de GDI a los que su aplicación estaba obligada. Algo así como 9.999. Cuando llegue a este límite, la aplicación se bloqueará con una excepción de memoria insuficiente, sin importar la cantidad de memoria disponible.

Así que podría estar haciendo algo similar, pero como mencionó que está trabajando con cadenas, me imagino que está fragmentando el montón y excediendo su capacidad. Si sus cadenas son lo suficientemente grandes, probablemente estén en el montón de objetos grandes. Creo que la implementación del LOH fue muy pobre en la versión inicial del framework. Si la memoria me sirve correctamente, los objetos no se desasignaron correctamente, lo que hace que sea muy fácil quedarse sin espacio solo en LOH.

Consulte estos enlaces para obtener alguna información más

http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/ http://msdn.microsoft.com/en-us/magazine/cc534993.aspx http://blogs.msdn.com/maoni/archive/2006/04/18/large-object-heap.aspx http://social.msdn.microsoft.com/Forums/en-US/clr/thread/08e6bd5f-613e-41ae-9ab1-b05c7ff2710f

9

Win32 tiene un límite de memoria de 2 GB por proceso.Bueno, 4 GB en realidad, pero 2 GB están reservados para kernel-mode, a menos que tenga la opción de inicio del sistema operativo /3GB.

+1

Solo muestra 1,6 GB, pero apuesto a que está perdiendo parte de eso por la fragmentación. –

+1

El blog de Mark Russinovich contiene información detallada sobre los límites de la memoria física de Windows- http://blogs.technet.com/markrussinovich/archive/2008/07/21/3092070.aspx – RichardOD

+1

También la arquitectura prescriptiva de P & P tiene algunos consejos sobre memoria- http://msdn.microsoft.com/en-us/library/ms998583.aspx#scalenetchapt17_topic9 – RichardOD

2

El constructor predeterminado de la lista <T> comienza con una matriz vacía como almacenamiento interno. Una llamada a Agregar (elemento T) comprueba si es necesario cambiar el tamaño de una matriz, y va a double la propiedad Capacity (a través del método EnsureCapacity). Cuando la propiedad de capacidad se establece que ...

  1. Crea una nueva matriz con el nuevo tamaño (el doble de la original!)
  2. Copia los elementos de la antigua a la nueva.
  3. Cambia la referencia interna en la nueva.

Por lo tanto, suponiendo una Capacidad de n implicaría que durante el cambio de tamaño tiene un uso de memoria total de 3n.

¿Cuántos elementos contiene su Lista cuando falla? Intenta usar el constructor que acepta una capacidad si sabes cuántos elementos se agregarán. Esto evita cualquier cambio de tamaño que pueda tener que hacerse (y puede arrojar su OutOfMemoryException directamente si necesita grandes bloques de memoria).

1

Olvídense de la fragmentación, LargeAddressAware o gcAllowVeryLargeObjects ... Mi problema con esta situación exacta se solucionó desactivando la casilla de verificación 'Preferir 32 bits' en la página Propiedades del proyecto de mi consola, en Build. Esto fue establecido por defecto ... ¿por qué?

+0

Funciona para mí también –

Cuestiones relacionadas