.Net Bitmap类构造函数(int,int)和(int,int,PixelFormat)抛出完美的参数上的ArgumentException

我有一些代码执行类似的操作(不相关的位被剪切):

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

任何人大部分时间都没事。 首先。 随着项目的继续,它在新的Bitmap线上开始失败。 它给出的错误是:“ArgumentException未处理。参数无效。” 没有提到哪个参数有问题或什么。 我很难过。 这就是我所知道的:

  1. 抛出此错误时,bmp1和bmp2从未为null。
  2. if语句的存在从未发挥过作用; 它没有经常死亡。
  3. 构造函数使用的两个示例都抛出了此错误。

我很想说这是一个内存错误,除了它没有提到任何类型。 前十几次这发生了超过18000的高度(因此上面的幻数)。 弄清楚它是我们系统的某种软屏障,我们只是将图像限制在那个高度,这使得exception在一段时间后消失。

对于一些样本数据,我现在看的例外情况是bmp1.Width在2550,bmp1.Height在6135和bmp2.Height在6285。

有人有主意吗?

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

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

真正发生的是这个位图需要太多连续的非托管内存来存储位图位,这比你的进程中的位图要多。 在32位操作系统上,您只能希望分配大约550兆字节的内存块。 从那里开始很快下山。

问题是地址空间碎片,程序的虚拟内存在各种地址存储混合的代码和数据。 总内存空间约为2千兆字节,但最大的漏洞远小于此。 你只能使用大量的小分配来消耗所有内存,大的内存会更快地失败。

长话短说:它试图告诉你,你所要求的大小不能得到支持。

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

检查bmp1或bmp2是否已处理(即使不为空)。 看这里:

神秘参数不是有效例外

有人有主意吗?

使用try-catch(Exception ex)包装抛出ArgumentException的调用,并进入exception块以查看原始exception。 它应该给你更多细节,比如哪个参数无效。

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