Be careful about exception after resource allocation


The following is a common code pattern

        Resource resource = GetResource();

        DoWork();           

        return resource;

If DoWork() throws exception, the resource will be leaked. We need to guard against this.

For example

        bool success = false;

        Resource resource = GetResource();

        try

        {

            DoWork();

            success = true;

            return resource;

        }

        finally

        {

            if (!success)

            {

                DisposeResource(resource);

            }

        }

Comments (6)

  1. barrkel says:

    I use rethrowing for the same concept:

    Resource resource = GetResource();

    try

    {

       DoWork();

       return resource;

    }

    catch

    {

       DisposeResource(resource);

       throw;

    }

    It saves having to fiddle with flags.

  2. Tanveer Badar says:

    If the CLR designers had the foresight to actually enable programmers to implement RAII idiom, none of this would be a problem.

    VC++ had to retrofit the concept with VC2005 in C++/CLI.

    Your best bet is to do what you did or implement IDisposable.

  3. yamazed says:

    I don’t know how to contact you with a question I have. So here it is for you:

    I want to programatically (C#) Ngen then GAC to boost performance. I have a list of assemblies. How would I do this using your GAC wrapper? We support XP and V. Any code samples will truly go far to help us.

    Thanks,

    ~yamazed

  4. WebDancer says:

    @barrkel: Your solution is not at all equal to the finally pattern. Catching and re-throwing the exception will "destroy" the original exception stack and the next catch (or WER) will not get the correct context.

  5. Alex says:

    @Stale: Using "throw;" without specifying an object will cause the caught exception to be propagated to the method that invoked the current method.  What you are describing is this situation —

    try

    {

     return 1/0;

    }

    catch(Exception ex) // Or (DivisionByZeroException ex)

    {

     //do something here

     throw ex;

    }

    In this case the site of the exception will be the "throw ex;" line instead of "return 1/0;".

    However, the problem with barrkel’s code is that he’s using exceptions to direct the normal logic.  If an exception can be prevented then it should be avoided.  While the Junfeng’s solution might feel unwieldy, it does follow current MSDN exception handling best practices. http://msdn.microsoft.com/en-us/library/seyhszts.aspx