2009-09-21 32 views
5

La nostra applicazione non funziona sul computer di un utente specifico con ERROR_NOT_ENOUGH_MEMORY ("Memoria insufficiente per elaborare questo comando").Risoluzione dei problemi ERROR_NOT_ENOUGH_MEMORY

L'errore sembra essere stato generato da qualche parte nel framework VCL di Delphi che stiamo utilizzando, quindi non sono sicuro di quale sia la funzione dell'API di Windows.

La memoria è un problema? Una chiamata al GlobalMemoryStatus ha pronunciato la seguente informazione:

  • dwTotalPhys - 1.063.150 mila (~ 1 GB)
  • dwAvailPhys - 26.735.000 (~ 27 MB)
  • dwAvailPage - 1,489 miliardi (~ 1,4 GB)

Mi sembra strano che Windows lascerebbe che la memoria fisica disponibile diventi così bassa quando è disponibile così tanto spazio nel file di paging, ma non ne so abbastanza della gestione della memoria virtuale di Windows per sapere se è normale o no . È?

Se non la memoria, quale limite di risorse viene colpito? Da quello che ho letto online, ERROR_NOT_ENOUGH_MEMORY potrebbe essere il risultato dell'applicazione che ha raggiunto uno dei vari limiti (oggetti GDI, oggetti USER, handle, ecc.) E non necessariamente memoria. Esiste un elenco completo di ciò che limita Windows applica? C'è un modo per scoprire quale limite viene colpito? Ho provato Google, ma non sono riuscito a trovare una panoramica sistematica.

+0

GDI è il mio primo punto di chiamata. Mentre è strano che stia accadendo solo sulla macchina di un utente, è lì che inizierei. Potrebbe anche essere qualcosa come il numero di maniglie che sono in uso, ecc. Buona fortuna! –

risposta

3

Il colpevole in questo caso era CreateCompatibleBitmap. Apparentemente Windows potrebbe imporre limiti di sistema abbastanza rigidi sulla memoria disponibile per bitmap dipendenti dalla periferica (vedere, ad esempio, this mailing list discussion), anche se il sistema in uso dispone di molta memoria e molte risorse GDI. (Questi limiti a livello di sistema sono apparentemente a causa di Windows può assegnare bitmap dipendente dalla periferica nella memoria della scheda video.)

La soluzione è semplice da usare bitmap indipendente (DIB), invece (anche se queste non possono offrire abbastanza buono di un prestazione). This KB article descrive come scegliere il formato DIB ottimale per un dispositivo.

Altri candidati per i limiti delle risorse (dalle risposte degli altri e la mia ricerca):

  • risorse GDI (da questa risposta) - facilmente controllato con GDIView
  • frammentazione della memoria virtuale (da questa risposta)
  • desktop heap - vedere here o here
3

Una causa più comune di questo errore rispetto a qualsiasi di quelli che hai elencato è la frammentazione dello spazio di memoria virtuale. Questa è una situazione in cui, mentre la memoria libera totale è abbastanza ragionevole, lo spazio libero è frammentato con vari bit dello spazio di memoria virtuale attualmente allocati. Quindi si può ottenere un errore di memoria esaurita quando una richiesta di memoria non può essere soddisfatta da un singolo blocco contiguo nonostante sia abbastanza in totale libero.

+0

Questo dovrebbe essere abbastanza facilmente verificabile provando la stessa cosa da un nuovo riavvio. Si potrebbe pensare che avrebbero provato quello prima di postarlo come una domanda su SO (ma le cose più stupide sono successe ...) –

+0

@ T.E.D. : Un riavvio non è più efficace del semplice uccidere il processo di errore e riprovare. Ogni processo ha il suo nuovo spazio di memoria virtuale quando viene creato per la prima volta. Il problema di solito sorge spontaneamente in un'app di lunga durata o rapidamente dove c'è una miscela di pezzi grandi e piccoli di memoria che vengono allocati e deallocati abbastanza rapidamente con vite diverse. Solitamente è un indicatore del fatto che alcuni blocchi di codice dovrebbero mantenere un elenco di buffer da riutilizzare anziché allocare e rilasciare costantemente la memoria. – AnthonyWJones

+0

L'utilizzo di FastMM in Delphi è migliore per prevenire la frammentazione della memoria virtuale. –

4

Verificare tutte le possibilità.

I problemi GDI possono essere monitorati utilizzando l'utilità gratuita GDIView. È un singolo file che gli utenti possono avviare senza un programma di installazione.

Inoltre, installare ProcessExplorer sulla macchina in questione.

Se non si ha accesso alla macchina, chiedere all'utente di effettuare schermate dello stato monitorato dalle applicazioni. Molto probabilmente, questo ti darà qualche suggerimento.

+0

GDIView fornisce interessante impressionante dettagli su "oggetti GDI". – Wolf

0

la mia risposta può essere un po 'in ritardo, ma, dal mio ritardo e Xperience con lo stesso problema, facendo tutte le prove, andare passo dopo passo, la creazione di DC, rilasciandolo, utilizzando DIBSection invece di CompatibleBitmap, utilizzando strumenti di perdite GDI/Memory, ecc

Alla fine (LOL) ho scoperto che :

Stavo cambiando la priorità di queste due chiamate, quindi l'intero problema è stato risolto.

DeleteDC(hdc);  //do it first (always before deleting objects) 
DeleteObject(obj); 
Problemi correlati