c# - Do I need to call UnlockBits on a Bitmap that lives on stack? - Stack Overflow

admin2025-04-21  1

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?

Share Improve this question asked Jan 22 at 23:01 meJustAndrewmeJustAndrew 6,64310 gold badges56 silver badges87 bronze badges 6
  • 1 @Hans Passant — Probably, OP means exceptions thrown by //do some processing. Then this processing can be put under try, and finally can call UnlockBits. Does it make sense? — it depends. – Sergey A Kryukov Commented Jan 23 at 0:23
  • 1 @SergeyAKryukov that is correct! – meJustAndrew Commented Jan 23 at 0:26
  • @HansPassant sorry if I mislead you, I am asking what if the extra code in between the LockBits and UnlockBits throws an exception? – meJustAndrew Commented Jan 23 at 0:27
  • Thank you for the clarification. However, the problem is that you are trying to return a bitmap. Just finally 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 reach return. If you use try-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
  • ... I can imagine the scenario when you can use the bitmap somehow even in case of exception, when you need to save only a part of processing in //do some processing, the part before throwing an exception, but it cannot be return. 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
 |  Show 1 more comment

1 Answer 1

Reset to default 0

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.

转载请注明原文地址:http://anycun.com/QandA/1745224417a90441.html