2009-09-21 16 views
5

Nuestra aplicación está fallando en la computadora de un usuario específico con ERROR_NOT_ENOUGH_MEMORY ("No hay suficiente espacio de almacenamiento disponible para procesar este comando").Solución de problemas ERROR_NOT_ENOUGH_MEMORY

El error aparentemente se está planteando en algún lugar profundo dentro del framework Delphi VCL que estamos usando, así que no estoy seguro de qué función de la API de Windows es responsable.

¿La memoria es un problema? Una llamada a GlobalMemoryStatus da la siguiente información:

  • dwTotalPhys - 1063150000 (~ 1 GB)
  • dwAvailPhys - 26735000 (~ 27 MB)
  • dwAvailPage - 1489000000 (~ 1,4 GB)

Me parece extraño que Windows permita que la memoria física disponible sea tan baja cuando hay tanto espacio disponible en el archivo de paginación, pero no sé lo suficiente sobre la administración de memoria virtual de Windows para saber si esto es normal o no. . ¿Lo es?

Si no hay memoria, ¿qué límite de recursos está siendo afectado? Según lo que leí en línea, ERROR_NOT_ENOUGH_MEMORY podría ser el resultado de que la aplicación tocara cualquiera de varios límites (objetos GDI, objetos USER, identificadores, etc.) y no necesariamente la memoria. ¿Hay una lista completa de los límites que Windows impone? ¿Hay alguna forma de averiguar qué límite está siendo golpeado? Probé con Google, pero no pude encontrar ninguna descripción sistemática.

+0

GDI es mi primer puerto de escala. Si bien es extraño que solo esté sucediendo en la máquina de un usuario, ahí es donde comenzaría. También podría ser algo así como el número de mangos que están en uso, etc. ¡Buena suerte! –

Respuesta

3

El culpable en este caso fue CreateCompatibleBitmap. Aparentemente, Windows puede imponer límites bastante estrictos para todo el sistema en la memoria disponible para mapas de bits dependientes del dispositivo (consulte, por ejemplo, this mailing list discussion), incluso si su sistema tiene suficiente memoria y muchos recursos de GDI. (Estos límites del sistema aparentemente son porque Windows puede asignar mapas de bits dependientes del dispositivo en la memoria de la tarjeta de video).

La solución es simplemente usar mapas de bits independientes del dispositivo (DIB) en su lugar (aunque estos pueden no ser tan buenos como actuación). This KB article describe cómo seleccionar el formato DIB óptimo para un dispositivo.

Otros candidatos para el límite de recursos (a partir de las respuestas de otros y mi propia investigación):

  • recursos GDI (a partir de esta respuesta) - fácilmente controladas con GDIView
  • fragmentación de memoria virtual (de esta respuesta)
  • montón de escritorio - ver here o here
3

Una causa más común de este error que cualquiera de los enumerados es la fragmentación del espacio de memoria virtual. Esta es una situación en la que, si bien la memoria libre total es bastante razonable, el espacio libre se fragmenta con varios bits del espacio de memoria virtual que se está asignando actualmente. Por lo tanto, puede obtener un error de falta de memoria cuando un bloque contiguo no puede satisfacer una solicitud de memoria a pesar de que es suficiente en total.

+0

Eso debería ser fácilmente comprobable probando lo mismo desde un nuevo reinicio. Uno pensaría que lo habrían intentado antes de publicarlo como una pregunta en SO (pero las cosas más tontas han sucedido ...) –

+0

@ T.E.D. : Un reinicio no es más efectivo que simplemente matar el proceso de fallas y volver a intentarlo. Cada proceso tiene su propio espacio de memoria virtual nuevo cuando se crea por primera vez. Por lo general, el problema surge de forma natural en una aplicación de larga ejecución o rápidamente cuando hay una gran cantidad de trozos grandes y pequeños de memoria asignados y desasignados con bastante rapidez con distintas vidas. Por lo general, es un indicador de que un poco de código debe mantener una lista de almacenamientos intermedios para volver a utilizar en lugar de asignar y liberar constantemente la memoria. – AnthonyWJones

+0

El uso de FastMM en Delphi es mejor para evitar la fragmentación de la memoria virtual. –

4

Compruebe todas las posibilidades.

Los problemas de GDI pueden controlarse utilizando la utilidad gratuita GDIView. Es un archivo único que los usuarios pueden iniciar sin un instalador.

Además, instale el ProcessExplorer en la máquina correspondiente.

Si no tiene acceso a la máquina, solicite al usuario que realice capturas de pantalla del estado monitoreado por las aplicaciones. Muy parecido, esto te dará una pista.

+0

GDIView da interesante impresionante detalles sobre "los objetos GDI". – Wolf

0

mi respuesta puede ser un poco más tarde, pero, desde mi último correo xperience con ese mismo problema, haciendo todas las pruebas, yendo paso a paso, creando DC, soltándolo, usando DIBSection en lugar de CompatibleBitmap, usando las herramientas de pérdida GDI/Memoria, etc.

Al final (LOL) encontré que :

Estaba cambiando la prioridad de estas dos llamadas, entonces se solucionó todo el problema.

DeleteDC(hdc);  //do it first (always before deleting objects) 
DeleteObject(obj); 
Cuestiones relacionadas