是否有一个原因Image.FromFile为无效的图像格式抛出OutOfMemoryException?

时间:2010-04-09 19:44:32

标签: c# exception exception-handling naming

我正在编写捕获此OutOfMemoryException的代码并抛出一个新的,更直观的异常:

/// ...
/// <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 );
    }
}

此代码是否为其用户所接受,或者OutOfMemoryException是否因特定原因故意被抛出?

4 个答案:

答案 0 :(得分:37)

不,这是历史。在.NET出现之前,GDI +写了很长一段时间。它的SDK包装器是用C ++编写的。 C ++中的例外情况是不确定的,并不是每个人都购买它们。谷歌没有例如。因此,要保持兼容,它会报告错误代码的问题。从来没有很好地扩展,库程序员将目标定为有意限制可能的错误代码的数量,它减轻了客户端程序员必须报告它们的负担。

GDI +在黑桃中有这个问题,它只定义了20个错误代码。对于如此大量的具有如此多外部依赖性的代码而言,这并非。这本身就是一个问题,有很多方法可以搞乱图像文件。图书馆的错误报告无法完全覆盖它们。事实上,在.NET定义的标准Exception派生类型之前很久就选择了这些错误代码,这无疑有帮助。

Status :: OutOfMemory错误代码被重载意味着不同的东西。有时它确实意味着内存不足,它无法分配足够的空间来存储位图位。遗憾的是,相同的错误代码报告了图像文件格式问题。这里的摩擦是它无法确定它从图像文件中读取的宽度*高度*像素是否有问题,因为位图没有足够的可用存储空间。或者,如果图像文件中的数据是垃圾。它假设图像文件不是垃圾,公平的电话,这是另一个程序的问题。所以OOM就是它的报道。

为完整起见,这些是错误代码:

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)
};

答案 1 :(得分:7)

嗯,这是一个很好的例子,说明异常并不总是意味着什么。 This particular caseOutOfMemoryException表示无效文件)可以追溯到.Net 1.0,它有一组更有限的异常类型,此库的程序员可以从中选择。我认为从那以后它没有被改变以保持向后兼容性(a.k.a。“在糟糕的情况下抛出好钱”)。

公平地说,我认为这是他们本可以做出的异常类型的最糟糕选择。当你打开一个文件,它碰巧很大,而你得到一个OutOfMemoryException时,可以合理地假设你实际上已经没有内存并且在一段时间内咆哮错误的树(这不止一个问题)在StackOverflow上关于这个)。

答案 2 :(得分:3)

如果是因为文件无效,可能只是想根据它认为的标题中的某些字节来猜测它需要多大的缓冲区。通过测试清楚地记录你的意图,你应该没事。

答案 3 :(得分:2)

这是一个误导性的例外。 Microsoft says

  

当您尝试在.NET Framework 1.0中使用Bitmap.FromFile方法时收到“System.OutOfMemoryException”错误消息

     

使用 Bitmap.FromFile 方法时,可能会出现此问题,并且满足下列条件之一:

     
      
  • 图像文件已损坏。
  •   
  • 图片文件不完整。
  •   
     

注意如果您的应用程序尝试在未完成写入文件的文件流上使用 Bitmap.FromFile 方法,则可能会遇到此问题。   *图像文件没有有效的图像格式,或者GDI +不支持文件的像素格式。   *该程序无权访问该图像文件。   * BackgroundImage 属性直接来自 Bitmap.FromFile 方法。

(位图来自Image)

当然,当您尝试加载太大的图像时,也可能会出现此异常。所以你需要考虑这个。