tags:

views:

364

answers:

3

I have some code that does something like this (Irrelevant bits snipped):

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

Anywho most of the time this ran fine. At first. As the project continued it started to fail on the new Bitmap line. The error it gives is: "ArgumentException was unhandled. Parameter is not valid." There's no mention of which parameter it has a problem with or anything. I'm stumped. Here's what I know for sure:

  1. bmp1 and bmp2 have never been null when this error is thrown.
  2. The if statement's presence has never made a difference; it dies just as frequently without.
  3. Both examples of the constructor use have thrown this error.

I'm tempted to say this is a memory error, except it doesn't mention anything of the sort. The first dozen times or so this happened the heights totalled over 18000 (hence the magic number above). Figuring it was some kind of soft barrier to our system, we just limited the images at that height which made the exceptions go away after a while.

For some sample data, the exception I'm looking at right now has bmp1.Width at 2550, bmp1.Height at 6135 and bmp2.Height at 6285.

Anyone have any ideas?

A: 

Anyone have any ideas?

Wrap the call that is throwing ArgumentException with a try-catch(Exception ex) and step into the exception block to see the raw exception. It should give you more detail, like which argument is supposedly invalid.

try
{
    bmp3 = new Bitmap(bmp1.Width, bmp1.Height + bmp2.Height);
}
catch (Exception ex)
{   
    throw;  // breakpoint here, examine "ex"
}
JMD
Right. Should've mentioned that I've tried this. It gives me almost no more information. There's no inner exception, the message (in it's entirety) is "Parameter is not valid.", source is labelled as "System.Drawing", and the stack trace has "at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)" at the top level. Not sure what else I could get from the exception.
AgroMan
That's interesting. And by *interesting* I mean, "May you lead an interesting life"-interesting. Two of the `ArgumentException` constructors accept a string parameterName, and it's *interesting* that the `Bitmap` constructor is not using it when clearly it's available.
JMD
A: 

Check whether bmp1 or bmp2 has been Disposed (even if not null). See here:

The Mysterious Parameter Is Not Valid Exception

Kyralessa
+6  A: 

GDI+ does not generate very good exception messages. The exception you got is flaky, this one will generate it reliably on my machine:

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

What's really going on is that this bitmap requires too much contiguous unmanaged memory to store the bitmap bits, more than is available in your process. On a 32-bit operating system, you can only ever hope to allocate a chunk of memory around 550 megabytes. That goes quickly down-hill from there.

The issue is address space fragmentation, the virtual memory of your program stores a mix of code and data at various addresses. Total memory space is around 2 gigabytes but the biggest hole is much smaller than that. You can only consume all memory with lots of small allocations, big ones fail much quicker.

Long story short: it is trying to tell you that the size you requested cannot be supported.

A 64-bit operating system doesn't have this problem. Also, WPF relies on WIC, an imaging library that's a lot smarter about allocating buffers for bitmaps.

Hans Passant
This, coupled with Kyralessa's link, pretty much explained the problem. Now I just have to fix the memory leak. :( Thanks guys!
AgroMan