Our website uses cookies to enhance your browsing experience.
Accept
to the top
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam

Webinar: C++ semantics - 06.11

>
>
>
V3101. Potential resurrection of 'this'…
menu mobile close menu
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Micro-Optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C#)
Problems related to code analyzer
Additional information
toggle menu Contents

V3101. Potential resurrection of 'this' object instance from destructor. Without re-registering for finalization, destructor will not be called a second time on resurrected object.

May 26 2016

The analyzer detected a suspicious destructor that deals with potentially incorrect object "resurrection".

The object destructor is invoked by the .NET garbage collector immediately before reclaiming the object. Destructor declaration is not obligatory in .NET Framework languages, as the garbage collector will reclaim the object anyway, even without its destructor being declared explicitly. Destructors are usually used when one needs to release unmanaged resources used by .NET objects before freeing these objects. File-system handles are one example of such resources, which cannot be released automatically by the garbage collector.

However, immediately before an object is reclaimed, the user can (intentionally or unintentionally) "resurrect" it before the garbage collector reclaims its memory. As you remember, the garbage collector frees objects that have become inaccessible, i.e. there are no references to these objects left. However, if you assign a reference to such an object from its destructor to a global static variable, for example, then the object will become visible to other parts of the program again, i.e. will be "resurrected". This operation may be executed multiple times.

The following example shows how such "resurrection" occurs:

class HeavyObject
{
    private HeavyObject()
    {
        HeavyObject.Bag.Add(this);
    }
    ...
    public static ConcurrentBag<HeavyObject> Bag;
    ~HeavyObject()
    {
        if (HeavyObject.Bag != null)
            HeavyObject.Bag.Add(this);
    }
}

Suppose we have object "HeavyObject", creation of which is a highly resource-intensive operation. Besides, this object cannot be used from different parts of the program simultaneously. Suppose also that we can create just a few instances of such objects at once. In our example, the "HeavyObject" type has open static field "Bag", which is a collection that will be used to store all the created instances of "HeavyObject" objects (they are be added to the collection in the constructor). This will allow getting an instance of type "HeavyObject" from anywhere in the program:

HeavyObject heavy;
HeavyObject.Bag.TryTake(out heavy);

Method "TryTake" will also delete the "heavy" instance from the "Bag" collection. That is, we can use only a limited number of instances of type "HeavyObject" (its constructor is closed) created in advance. Now, suppose we do not need the "heavy" instance created by the "TryTake" method anymore and all references to this object have been deleted. Then, some time later, the garbage collector will invoke the object's destructor, where this object will be again added to the "Bag" collection, i.e. "resurrected" and made available to the user, without having to re-create it.

However, our example contains an error that will make the code work differently from what is described above. This error deals with an assumption that the "resurrected" object's destructor will be invoked each time the object becomes invisible to the program (i.e. there are no references to it left). What will actually happen is that the destructor will be called only once, i.e. the object will be "lost" the next (a second) time the garbage collector attempts to reclaim it.

To ensure correct work of the destructor when the object is "resurrected", this object must be re-registered using method GC.ReRegisterForFinalize:

~HeavyObject()
{
    if (HeavyObject.Bag != null)
    {
        GC.ReRegisterForFinalize(this);
        HeavyObject.Bag.Add(this);
    }
}

This solution guarantees that the destructor will be called each time before the garbage collector tries to reclaim the object.