2010-04-09 8 views
26

ich Code schreibe, dass diese OutOfMemoryException und wirft eine neue, intuitive Ausnahme abfängt:Gibt es einen Grund, dass Image.FromFile eine OutOfMemoryException für ein ungültiges Bildformat auslöst?

/// ... 
/// <exception cref="FormatException">The file does not have a valid image format.</exception> 
public static Image OpenImage(string filename) 
{ 
    try 
    { 
     return Image.FromFile(filename); 
    } 
    catch(OutOfMemoryException ex) 
    { 
     throw new FormatException("The file does not have a valid image format.", ex); 
    } 
} 

Ist dieser Code seinem Benutzer akzeptabel ist oder OutOfMemoryException absichtlich aus einem bestimmten Grund geworfen zu werden?

Antwort

36

Nein, es ist Geschichte. GDI + wurde schon eine ganze Weile geschrieben, bevor .NET überhaupt auf den Markt kam. Der SDK-Wrapper dafür wurde in C++ geschrieben. Ausnahmen sind in C++ zweifelhaft, nicht jeder kauft sie ein. Google nicht zum Beispiel. Um es kompatibel zu halten, meldet es Probleme mit Fehlercodes.Das skaliert einfach nie, Bibliotheks-Programmierer machen es sich zur Aufgabe, die Anzahl der möglichen Fehlercodes bewusst zu begrenzen, um die Belastung des Client-Programmierers zu reduzieren.

GDI + hat dieses Problem in Pik, es definiert nur 20 Fehlercodes. Das ist nicht viel für so ein großes Stück Code mit so vielen externen Abhängigkeiten. Was an sich schon ein Problem ist, gibt es eine Vielzahl von Möglichkeiten, eine Image-Datei zu vermasseln. Keinesfalls kann die Fehlerberichterstattung einer Bibliothek so feinkörnig sein, dass sie alle abdeckt. Die Tatsache, dass diese Fehlercodes lange vor der Verwendung von Standard-Ausnahme-abgeleiteten Typen von .NET ausgewählt wurden, half sicherlich nicht.

Der Status :: OutOfMemory Fehlercode wurde überladen, um verschiedene Dinge zu bedeuten. Manchmal bedeutet es wirklich nicht genügend Arbeitsspeicher, es kann nicht genügend Speicherplatz zum Speichern der Bitmap-Bits reservieren. Leider wird ein Problem mit dem Bilddateiformat mit demselben Fehlercode gemeldet. Die Reibung ist hier, dass es unmöglich entscheiden kann, ob die Breite * Höhe * Pixel, die es aus der Bilddatei liest, ein Problem ist, da nicht genügend Speicher für die Bitmap verfügbar ist. Oder wenn die Daten in der Bilddatei Junk sind. Es wird angenommen, dass die Image-Datei kein Junk ist, fairer Aufruf, das ist ein anderes Programmproblem. So OOM ist, was es berichtet.

Für Vollständigkeit, das sind die Fehlercodes:

enum Status 
{ 
    Ok = 0, 
    GenericError = 1, 
    InvalidParameter = 2, 
    OutOfMemory = 3, 
    ObjectBusy = 4, 
    InsufficientBuffer = 5, 
    NotImplemented = 6, 
    Win32Error = 7, 
    WrongState = 8, 
    Aborted = 9, 
    FileNotFound = 10, 
    ValueOverflow = 11, 
    AccessDenied = 12, 
    UnknownImageFormat = 13, 
    FontFamilyNotFound = 14, 
    FontStyleNotFound = 15, 
    NotTrueTypeFont = 16, 
    UnsupportedGdiplusVersion = 17, 
    GdiplusNotInitialized = 18, 
    PropertyNotFound = 19, 
    PropertyNotSupported = 20, 
#if (GDIPVER >= 0x0110) 
    ProfileNotFound = 21, 
#endif //(GDIPVER >= 0x0110) 
}; 
+3

Fast * alle * dieser wäre eine bessere Wahl gewesen als 'OutOfMemory', auch' GenericError'. – MusiGenesis

+11

Insbesondere das 'Unknown ImageFormat' scheint für ein Format geeignet zu sein, das nicht verstanden werden kann. –

7

Nun, es ist ein gutes Beispiel dafür, dass eine Ausnahme nicht immer das bedeutet, was sie sagt. This particular case (OutOfMemoryException für eine ungültige Datei) stammt aus .NET 1.0, die eine begrenzte Anzahl von Ausnahmetypen hatte, aus denen die Programmierer dieser Bibliothek wählen könnten. Ich gehe davon aus, dass es seither nicht geändert wurde, um Abwärtskompatibilität aufrechtzuerhalten (a.k.a. "gutes Geld nach schlechtem werfen").

Um fair zu sein, ich denke, es war die schlechteste mögliche Wahl für Ausnahme-Typ, den sie hier hätten machen können. Wenn du eine Datei öffnest und sie groß ist und du eine OutOfMemoryException bekommst, ist es logisch anzunehmen, dass du nicht genug Speicher hast und den falschen Baum für eine Weile bellst (es gibt mehr als eine Frage zu StackOverflow)).

3

Wenn es ist, weil die Datei ungültig ist, versucht es wahrscheinlich nur, wie groß ein Puffer benötigt wird, basierend auf einigen Bytes in dem, was es denkt, ist der Header. Dokumentieren Sie Ihre Absicht klar mit einem Test und Sie sollten in Ordnung sein.

2

Es ist eine irreführende Ausnahme. says Microsoft:

Sie erhalten eine "System.OutOfMemoryException" Fehlermeldung, wenn Sie versuchen, die Bitmap.FromFile Methode in .NET Framework 1.0 verwenden

kann dieses Problem auftreten, wenn Sie die verwenden Bitmap.FromFile Methode und eine der folgenden Bedingungen ist erfüllt:

  • Die Bilddatei ist beschädigt.
  • Die Bilddatei ist unvollständig.

Hinweis: Sie können dieses Problem auftreten, wenn die Anwendung versucht, die Bitmap.FromFile Methode auf einem Datei-Stream zu verwenden, die nicht beendet werden in eine Datei geschrieben werden. * Die Bilddatei hat kein gültiges Bildformat oder GDI + unterstützt das Pixelformat der Datei nicht. * Das Programm hat keine Berechtigungen für den Zugriff auf die Bilddatei. * Die BackgroundImage Eigenschaft wird direkt von der Bitmap.FromFile Methode festgelegt.

(Bitmap stammt von Image)

Natürlich ist es auch möglich, diese Ausnahme zu erhalten, wenn Sie versuchen, ein Bild zu laden, die zu groß ist. Das musst du also beachten.

+0

Es ist fast nicht einmal wert Hinzufügen der Verbindung, wenn es der erste Treffer bei Google ist. :) – MusiGenesis

+2

@MusiGenesis: Man könnte argumentieren, dass es sich nicht lohnt, die Frage überhaupt zu beantworten. :) (Also warum habe ich? Ich weiß es nicht) –