1

In a C++ Builder 6 test project, I try to understand the relation between the TWinControl classes of the VCL and Windows user objects, because I'm hunting a leak of user objects in my original application where I use some levels of nested frames, created periodically at runtime, that causes my application to crash after some days.

In the test project I observe a strange behaviour. When I add a dynamically created TFrame object to a panel, the count of user objects increases by 2. If I remove a frame by deletion, the user object count is decreased by 1. If I add it again, the increment is 1. If I add more than 1 frame, the increment is 2 after exceeding the last maximum value of frames. This is the code to reproduce this:

MainForm.cpp

#include <vcl.h>
#pragma hdrstop

#include "MainFrm.h"

#pragma resource "*.dfm"
TMainForm *MainForm;

int UserObjectCount() {
    return GetGuiResources(GetCurrentProcess(), 1);
}

__fastcall TMainForm::TMainForm(TComponent* Owner)
    : TForm(Owner)
{
}

void __fastcall TMainForm::AddButtonClick(TObject *Sender)
{
    String msg = "add: "+IntToStr(UserObjectCount())+",";
    (new TFrame(static_cast<TComponent*>(NULL)))->Parent = FramesPanel;
    trace(msg+IntToStr(UserObjectCount()));
}

void __fastcall TMainForm::RemoveButtonClick(TObject *Sender)
{
    if (!FramesPanel->ControlCount) return;
    String msg = "rem: "+IntToStr(UserObjectCount())+",";
    FramesPanel->Controls[0]->Free();
    trace(msg+IntToStr(UserObjectCount()));
}

void TMainForm::trace(const String& msg)
{
    TraceMemo->Lines->Add(msg);
}

It looks like a kind of caching. See the (grouped) excerpt of the trace (format action: before,after):

add: 28,30
rem: 30,29

add: 29,30
add: 30,32
rem: 32,31
rem: 31,30

add: 30,31
add: 31,32
add: 32,34
rem: 34,33
rem: 33,32
rem: 32,31

Another observation: If I use TPanel instead of TFrame, the behaviour is is trivial.

As to understand whether this is a Windows feature, I built another test application with Lazarus (Google didn't help). Here the user object count behaviour is unsurprising: increment and decrement compensate each other.

What is the explanation of this caching-like behaviour? How to get back to the initial count of user objects?

I'm sorry for pushing you back into the old times of BCB6.

Wolf
  • 9,679
  • 7
  • 62
  • 108
  • You did not show what you have put onto the `TTestFrame`, or how you are performing your trace logging, or what your trace logging actually represents (what objects are you tracking?). Please provide a [MCVE](http://stackoverflow.com/help/mcve) demonstrating what you are describing. That being said, the VCL does do a small amount of caching of GDI objects (fonts, pens, brushes, bitmaps) using reference counts to manage their lifetimes. It does not cache user objects, like HWNDs. – Remy Lebeau Oct 13 '15 at 00:57
  • @RemyLebeau Thanks for looking into this. The TTestFrame does not contain any controls in my last test, I deleted all of the contents after seeing the discrepancy in the user object balance. I'll soon reduce my test project to a minimum and then expand my snippets here in the question. It will be some code for 2 units, maybe the .dfm files can be omitted... – Wolf Oct 13 '15 at 06:00
  • @RemyLebeau I added the code to reproduce the behaviour, I left out header and .dfm, they are trivial, but I can add them as well. – Wolf Oct 13 '15 at 10:12

0 Answers0