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

时间:2022-02-08 19:50:27

I am writing code that catches this OutOfMemoryException and throws a new, more intuitive exception:

我正在编写捕获此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 );    }}

Is this code acceptable to its user, or is OutOfMemoryException intentionally being thrown for a particular reason?

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

4 个解决方案

#1


37  

No, it is history. GDI+ was written quite a while before .NET ever came around. The SDK wrapper for it was written in C++. Exceptions are iffy in C++, not everybody buys into them. Google doesn't for example. So to keep it compatible it reports problems with error codes. That just never scales well, library programmers make it a goal to intentionally limit the number of possible error codes, it lessen the burden on the client programmer having to report them.

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

GDI+ has this problem in spades, it defines only 20 error codes. That is not much for such a large chunk of code with so many external dependencies. Which in itself is a problem, there are a gazillion ways to mess up an image file. No way that a library's error reporting can be fine-grained enough to cover them all. The fact that these error codes were picked long before .NET defined standard Exception derived types certainly didn't help.

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

The Status::OutOfMemory error code got overloaded to mean different things. Sometimes it really does mean out of memory, it can't allocate enough space to store the bitmap bits. Sadly, an image file format problem is reported by the same error code. The friction here is that it cannot possibly decide if the width * height * pixels it read from the image file is a problem because there isn't enough storage available for the bitmap. Or if the data in the image file is junk. It assumes that image file is not junk, fair call, that's another program's problem. So OOM is what it reports.

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

For completeness, these are the error codes:

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

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

#2


7  

Well, it's a good example of how an exception doesn't always mean what it says. This particular case (OutOfMemoryException for an invalid file) dates back to .Net 1.0, which had a more limited set of exception types from which the programmers of this library could choose. I assume it hasn't been changed since then to maintain backwards compatibility (a.k.a. "throwing good money after bad").

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

To be fair, I think it was about the worst possible choice for exception type they could have made here. When you open a file, and it happens to be big, and you get an OutOfMemoryException, it's logical to assume that you're actually out of memory and go barking up the wrong tree for awhile (there's more than one question on * about this).

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

#3


3  

If it's because the file is invalid, it's probably just trying to guess how big a buffer it needs based on some bytes in what it thinks is the header. Document your intent clearly with a test and you should be fine.

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

#4


2  

It's a misleading exception. Microsoft says:

这是一个误导性的例外。微软说:

You receive a "System.OutOfMemoryException" error message when you try to use the Bitmap.FromFile method in the .NET Framework 1.0

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

This problem may occur when you use the Bitmap.FromFile method and one of the following conditions is true:

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

  • The image file is corrupted.
  • 图像文件已损坏。

  • The image file is incomplete.
  • 图像文件不完整。

Note You may experience this problem if your application is trying to use the Bitmap.FromFile method on a file stream that is not finished writing to a file. * The image file does not have a valid image format or GDI+ does not support the pixel format of the file. * The program does not have permissions to access the image file. * The BackgroundImage property is set directly from the Bitmap.FromFile method.

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

(Bitmap descends from Image)

(位图来自Image)

Of course, it's also possible to get this exception when you try to load an image which is too big. So you need to consider that.

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

#1


37  

No, it is history. GDI+ was written quite a while before .NET ever came around. The SDK wrapper for it was written in C++. Exceptions are iffy in C++, not everybody buys into them. Google doesn't for example. So to keep it compatible it reports problems with error codes. That just never scales well, library programmers make it a goal to intentionally limit the number of possible error codes, it lessen the burden on the client programmer having to report them.

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

GDI+ has this problem in spades, it defines only 20 error codes. That is not much for such a large chunk of code with so many external dependencies. Which in itself is a problem, there are a gazillion ways to mess up an image file. No way that a library's error reporting can be fine-grained enough to cover them all. The fact that these error codes were picked long before .NET defined standard Exception derived types certainly didn't help.

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

The Status::OutOfMemory error code got overloaded to mean different things. Sometimes it really does mean out of memory, it can't allocate enough space to store the bitmap bits. Sadly, an image file format problem is reported by the same error code. The friction here is that it cannot possibly decide if the width * height * pixels it read from the image file is a problem because there isn't enough storage available for the bitmap. Or if the data in the image file is junk. It assumes that image file is not junk, fair call, that's another program's problem. So OOM is what it reports.

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

For completeness, these are the error codes:

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

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

#2


7  

Well, it's a good example of how an exception doesn't always mean what it says. This particular case (OutOfMemoryException for an invalid file) dates back to .Net 1.0, which had a more limited set of exception types from which the programmers of this library could choose. I assume it hasn't been changed since then to maintain backwards compatibility (a.k.a. "throwing good money after bad").

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

To be fair, I think it was about the worst possible choice for exception type they could have made here. When you open a file, and it happens to be big, and you get an OutOfMemoryException, it's logical to assume that you're actually out of memory and go barking up the wrong tree for awhile (there's more than one question on * about this).

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

#3


3  

If it's because the file is invalid, it's probably just trying to guess how big a buffer it needs based on some bytes in what it thinks is the header. Document your intent clearly with a test and you should be fine.

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

#4


2  

It's a misleading exception. Microsoft says:

这是一个误导性的例外。微软说:

You receive a "System.OutOfMemoryException" error message when you try to use the Bitmap.FromFile method in the .NET Framework 1.0

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

This problem may occur when you use the Bitmap.FromFile method and one of the following conditions is true:

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

  • The image file is corrupted.
  • 图像文件已损坏。

  • The image file is incomplete.
  • 图像文件不完整。

Note You may experience this problem if your application is trying to use the Bitmap.FromFile method on a file stream that is not finished writing to a file. * The image file does not have a valid image format or GDI+ does not support the pixel format of the file. * The program does not have permissions to access the image file. * The BackgroundImage property is set directly from the Bitmap.FromFile method.

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

(Bitmap descends from Image)

(位图来自Image)

Of course, it's also possible to get this exception when you try to load an image which is too big. So you need to consider that.

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