【问题标题】:.Net Bitmap class constructor (int, int) and (int, int, PixelFormat) throws ArgumentException on perfectly good arguments.Net Bitmap 类构造函数 (int, int) 和 (int, int, PixelFormat) 在非常好的参数上抛出 ArgumentException
【发布时间】:2009-12-22 20:47:13
【问题描述】:

我有一些代码可以做这样的事情(不相关的部分被剪掉了):

void foo(Bitmap bmp1, Bitmap bmp2)
{
    Bitmap bmp3;
    if(something)
        bmp3 = new Bitmap(bmp1.Width, bmp1.Height + bmp2.Height);
    else
        bmp3 = new Bitmap(bmp1.Width, 18000);
    (more stuff here that runs fine)
}

任何人大部分时间都运行良好。首先。随着项目的继续,它开始在新的位图行上失败。它给出的错误是:“ArgumentException 未处理。参数无效。”没有提到它有问题的参数或任何东西。我难住了。以下是我确定的:

  1. bmp1 和 bmp2 从未为空 何时引发此错误。
  2. if 语句的存在 从来没有改变过;它死了 经常没有。
  3. 构造函数的两个示例都使用 已抛出此错误。

我很想说这是一个内存错误,但它没有提到任何类似的东西。前十几次发生这种情况,高度总计超过 18000 (因此上面的神奇数字)。考虑到这是对我们系统的某种软屏障,我们只是将图像限制在该高度,让异常在一段时间后消失。

对于一些示例数据,我现在正在查看的异常是 bmp1.Width 为 2550,bmp1.Height 为 6135,bmp2.Height 为 6285。

有人有什么想法吗?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    GDI+ 不会生成非常好的异常消息。你得到的异常是片状的,这个会在我的机器上可靠地生成它:

        private void button1_Click(object sender, EventArgs e) {
            var bmp = new Bitmap(20000, 20000);
        }
    

    实际发生的情况是,此位图需要太多连续的非托管内存来存储位图位,超过了您的进程中可用的内存。在 32 位操作系统上,您只能希望分配大约 550 兆字节的内存块。从那里开始迅速走下坡路。

    问题是地址空间碎片,程序的虚拟内存在不同的地址存储混合的代码和数据。总内存空间约为 2 GB,但最大的漏洞比这要小得多。您只能通过大量小分配来消耗所有内存,大分配失败得更快。

    长话短说:它试图告诉您无法支持您请求的大小。

    64 位操作系统没有这个问题。请务必通过 Project > Properties > Build 选项卡来利用它,Platform target = AnyCPU 和 Prefer 32-bit = unticked。此外,WPF 依赖于 WIC,这是一个在为位图分配缓冲区方面更加智能的图像库。

    【讨论】:

    • 这个,再加上 Kyralessa 的链接,几乎解释了这个问题。现在我只需要修复内存泄漏。 :( 谢谢大家!
    • 实际上,我在 Widows7 64 位上使用 VisualStudio 进行调试时遇到了同样的问题。所以 64 位操作系统并不能完全阻止它。
    • 将您的 EXE 项目的平台目标设置更改为 AnyCPU,这样您就可以真正利用 64 位地址空间。
    【解决方案2】:

    检查 bmp1 或 bmp2 是否已被 Disposed(即使不为空)。见这里:

    The Mysterious Parameter Is Not Valid Exception

    【讨论】:

      【解决方案3】:

      有人有什么想法吗?

      try-catch(Exception ex) 包装抛出ArgumentException 的调用,然后进入异常块以查看原始异常。它应该给你更多的细节,比如哪个参数被认为是无效的。

      try
      {
          bmp3 = new Bitmap(bmp1.Width, bmp1.Height + bmp2.Height);
      }
      catch (Exception ex)
      {   
          throw;  // breakpoint here, examine "ex"
      }
      

      【讨论】:

      • 对。应该提到我已经尝试过了。它几乎没有给我更多信息。没有内部异常,消息(全部)是“参数无效。”,源标记为“System.Drawing”,堆栈跟踪具有“在 System.Drawing.Bitmap..ctor(Int32 width, Int32 高度,PixelFormat 格式)”在顶层。不知道我还能从异常中得到什么。
      • 这很有趣。 有趣我的意思是,“愿你过上有趣的生活”——有趣。两个ArgumentException 构造函数接受一个字符串参数名称,有趣Bitmap 构造函数在明确可用时并未使用它。
      • 这个问题有什么解决办法吗?
      • @FabianoLothor,上面接受的答案似乎很好地解释了它。 IE。例外情况很糟糕,但问题是一成不变的:没有足够的连续内存可用于您尝试分配的位图大小。
      • 我通过使用不同类别的 iTextSharp 解决了我的问题。我现在正在使用 wkhtmltopdf 项目。
      猜你喜欢
      • 2013-08-17
      • 1970-01-01
      • 2014-07-25
      • 1970-01-01
      • 2018-05-30
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      相关资源
      最近更新 更多