I am using a Bitmap as a local variable that I manipulate and return. I am wondering if I should add a finally block with UnlockBits or leave the call without try finally block.
{
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
//do some processing
bmp.UnlockBits() //should I add this call in a finally?
return bmp;
}
I am asking only in case of exception, so that the UnlockBits part does not get called. This confuses me as I don't see this try finally in the msdn examples and the bitmap in the case of exception should be collected anyway as it's on stack.
My question can be rephrased as Does LockBits do something that can cause a memory leak or something bad to happen if not calling UnlockBits?
I am using a Bitmap as a local variable that I manipulate and return. I am wondering if I should add a finally block with UnlockBits or leave the call without try finally block.
{
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
//do some processing
bmp.UnlockBits() //should I add this call in a finally?
return bmp;
}
I am asking only in case of exception, so that the UnlockBits part does not get called. This confuses me as I don't see this try finally in the msdn examples and the bitmap in the case of exception should be collected anyway as it's on stack.
My question can be rephrased as Does LockBits do something that can cause a memory leak or something bad to happen if not calling UnlockBits?
First of all, the bitmap object will live on the heap. Only the bitmap reference will be on the stack.
For your actual question, if you are not sure if something is safe or not, err on the side of caution. In this case that would mean using try/finally. Note that you should also make sure to dispose the bitmap in case of exceptions:
var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
try{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
try{
//do some processing
return bmp;
}
finally{
bmp.UnlockBits();
}
}
catch{
bmp?.Dispose();
throw;
}
Is all of this required to avoid memory leaks? Probably not, managed memory will be cleaned up by the GC regardless, and any class that owns unmanaged resources should have a finalizer to do cleanup in cases where the object was not disposed correctly. But you should try to not rely on the finalizer if you can help it.
It will also depend on the error tolerance of the application and how much parameter validation you are doing. You might for example validate the width and height parameters, and specify that any exception during processing is considered fatal. But this kind of reasoning is really only possible when writing an application, or an internal library. If you are writing a public library you should try to ensure it is well behaved even when used incorrectly.
//do some processing
. Then this processing can be put undertry
, andfinally
can callUnlockBits
. Does it make sense? — it depends. – Sergey A Kryukov Commented Jan 23 at 0:23LockBits
andUnlockBits
throws an exception? – meJustAndrew Commented Jan 23 at 0:27finally
won't block propagation of the exception. Then the exception should be caught somewhere closer the top of stack. But your bitmap will be lost, because the execution won't reachreturn
. If you usetry
-catch
-finally
block, you can block the propagation of the exception, but this is not a good thing. Exceptions should be caught rarely, for all code deeper on stack the best strategy is: let go... – Sergey A Kryukov Commented Jan 23 at 0:46//do some processing
, the part before throwing an exception, but it cannot bereturn
. So, think based on that. Generally, the scenarios when you block the propagation of exceptions anywhere except the very top of stack of each thread, should be very rare. For example, when you need to compensate the bug in a library you cannot patch... – Sergey A Kryukov Commented Jan 23 at 0:49