2013-02-18 11 views
5

Il nostro software esegue il rendering di disegni tecnici. Un disegno particolare ha causato l'arresto anomalo dell'applicazione ogni volta con un valore OutOfMemoryException. All'indagine, nulla sembrava fuori dall'ordinario; l'app non ha richiesto molta memoria, non ha utilizzato molte maniglie. Ho provato a rilevare l'eccezione e l'app ha terminato il disegno senza lanciarne un altro. In effetti, c'era sempre solo l'OutOfMemoryException, ed era sempre la stessa primitiva grafica a causarlo.Arresto riproducibile tramite Graphics.DrawArc

Il seguente codice è il minimo richiesto per causare questo particolare arresto anomalo. Sembra che l'esatta combinazione di dimensioni dell'immagine, stile penna e coordinate causi l'eccezione. Arrotondare le coordinate fino a tre decimali fa scomparire, così come ridurre le dimensioni della grafica o utilizzare una penna senza tratteggio.

using (Bitmap b = new Bitmap(200, 200)) 
{ 
    using (Graphics g = Graphics.FromImage(b)) 
    { 
    using (Pen p = new Pen(Color.Black)) 
    { 
     p.DashPattern = new float[]{10.0f, 2.0f}; 

     RectangleF r = new RectangleF(
     BitConverter.ToSingle(new byte[]{0xD3, 0x56, 0xB3, 0x42}, 0), 
     BitConverter.ToSingle(new byte[]{0x87, 0x2D, 0x17, 0x43}, 0), 
     BitConverter.ToSingle(new byte[]{0xE2, 0x81, 0xD1, 0x3F}, 0), 
     BitConverter.ToSingle(new byte[]{0xE2, 0x81, 0xD1, 0x3F}, 0)); 
     float st = BitConverter.ToSingle(new byte[]{0x6B, 0xF6, 0x1A, 0x42}, 0); 
     float sw = BitConverter.ToSingle(new byte[]{0x6D, 0x33, 0x4F, 0x40}, 0); 

     g.DrawArc(p, r, st, sw); 
    } 
    } 
} 

In questo caso non è complicato per creare una soluzione, ma mi chiedevo se qualcuno avesse una spiegazione per questo.

risposta

4

System.Drawing è un wrapper per GDI +, una libreria non gestita che ha preceduto il rilascio di .NET da molti anni. Soffre di un tipico problema con una C api, la segnalazione degli errori è piuttosto scarsa. GDI + ha solo 20 codici di errore distinti, non tanto per una porzione così grande di codice. Sono anche molto opachi, un particolare doozy è Status :: GenericError. Un errore piuttosto comune che viene restituito per molte possibili condizioni di errore che non hanno nulla in comune.

System.Drawing potrebbe fare molto poco per rendere questi codici di errore più descrittivi, dato che non erano descrittivi per design. Status :: OutOfMemory si adatta anche a questo modello. Molto poco potrebbe farlo, ma generare un'eccezione gestita che significa la stessa cosa. Purtroppo non è stata una grande scelta perché OutOfMemoryException è molto specifico in .NET.

Un sacco di perdite qui con alcuni modi per vincere. Hai solo bisogno di prendere la segnalazione di errore poveri di GDI + al valore nominale e patch per il problema. Con un'alta probabilità in questo caso, evitare di usare una penna tratteggiata per archi molto piccoli risolverà il tuo problema. Non puoi comunque vedere lo schema del trattino.

+0

Molto informativo, grazie. Non mi è venuto in mente che la segnalazione degli errori GDI potrebbe essere così limitata. – waldrumpus

Problemi correlati