user1296153
user1296153

Reputation: 585

C++/Cli Destructors are not called

I am trying to investigate a memory leak problem and I found out that destructors in my library are not even called and I have the following code:

PPCamNET::Native::PpQueue::PpQueue(int capacity) : m_capacity(capacity), m_array(nullptr), m_head(0), m_tail(0)
{
    // Quick fix for case when capacity is 1 (single snap) 
    // and Push function crashes on 1st frame
    if (m_capacity == 1)
        m_capacity = 2;
    m_array = new FrameData[m_capacity];
    m_pushes = 0;
    m_pops = 0;
}

The above constructor's destructor should be called after PpQueue is destroyed, but it is not stopping at the break point.

PPCamNET::Native::PpQueue::~PpQueue()
{
    delete[] m_array; //<==== here I set a break point
}

PPQueue instance is created by AcqCache constructor.

PPCamNET::Internal::AcqCache::AcqCache(AcqBuffer^ acqBuffer)
{
    //m_stopWatchPush = Stopwatch::StartNew();
    //m_stopWatchPop = Stopwatch::StartNew();


    m_acqBuffer = acqBuffer;
    m_cacheLock = gcnew Object();
    m_processFrameRunning = true;
    try
    {
        m_frameDataCache = new PpQueue(acqBuffer->BufferSize / 2 + 1);

AcqCache destructor removes m_frameDataCache, which is PpQueue.

PPCamNET::Internal::AcqCache::~AcqCache()
{
    m_processFrameRunning = false;
    delete m_frameDataCache; // <== here another break point but not called
    delete[] m_frameInfoBuffer;
}

Finally the constructor of Acqusition creates an instance of m_acqCache with gcnew.

PPCamNET::Internal::Acquisition::Acquisition(AcqBuffer^ acqBuffer, 
        CameraSettings^ camSettings)
{
    m_eofEvent = gcnew AutoResetEvent(false);
    m_acqCache = gcnew AcqCache(acqBuffer);

I am puzzled why these destructors aren't called. Is this because GC didn't kick in to clear up m_acqCache causing other desructors not being called ?

Thanks,

Upvotes: 2

Views: 827

Answers (1)

Ben Voigt
Ben Voigt

Reputation: 283793

GC will not call a destructor. The C++/CLI compiler translates destructors into IDisposable::Dispose() implementation, and has a different syntax (ClassName::!ClassName) which gets translated to Finalize.

C# wrongly confuses this issue by using the name "destructor" for the CLR Finalize function. Finalizers are not deterministic. The Dispose() function is not called automatically by GC. Not difficult once you know what's going on, but the terminology sure leads to confusion.

Upvotes: 3

Related Questions