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

8 .net c#

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

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)
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

有人有主意吗?

Han*_*ant 19

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

    private void button1_Click(object sender, EventArgs e) {
        var bmp = new Bitmap(20000, 20000);
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 实际上,我在Widows7 64bit上使用VisualStudio进行调试时遇到同样的问题.所以64位操作系统并不能完全阻止它. (2认同)