Jump to content
Sign in to follow this  
shineworld

Strange memory leak with checkbox

Recommended Posts

Hi all.

What I love of Delphi is memory management and overall the integration of FastMM and related memory leak management.

All my projects are Memory Leak Free (just thanks to reports of FastMM which permits me to create a better code).

 

Now I'm migrating some programs to Python using DelphiVCL and I'm falling into odd memory leaks.

 

In a Python (3.9.12) application that uses DelphiVCL (0.1.40) I've noticed a continuous memory leak in some simple operations

with VCL objects like Checkbox.

 

I've attached a very simple Python program that uses a Timer to constantly update the Enabled state of a Checkbox.

In the sample, I've also added a const to enable a tracemalloc and confirm the continue grow of memory used by <Checkbox>.Enabled = True

# enable/disable tracemalloc to exclude the memory impact of tracemalloc
TRACEMALLOC_ENABLED = False

 

By default, TRACEMALLOC_ENABLED is set to False to remove any impact of tracemalloc framework.

If enabled, the first mouse down on the form capture the BASE snapshot of memory.

Any following mouse down, report on console the comparison of current snapshot with the first.

Initially, tracemalloc internals is in the top ten results, but after some time Checkbox1.Enabled = True gain the top.

 

If I disable the interesting lines, commenting on them, any memory leak disappears:

    def __on_timer(self, sender):
        """
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        self.CheckBox1.Enabled = True
        """

I've placed many CheckBox1.Enabled to exasperate the case-test but usually, I do this for a lot of controls in update events.

 

This is the memory usage captured with Process Explorer on running Python process with TRACEMALLOC_ENABLED = False:

image.thumb.png.4330030421ee48cab25c7c9c0ea5800e.png
 

 

 

test.zip

Edited by shineworld
typo

Share this post


Link to post

Just to clarify.   

 

a)  No memory leakage happens if your timer routine is:

 

    def __on_timer(self, sender):
        pass

 

b)  The increase in memory usage increases indefinitely when self.CheckBox1.Enabled = True is called inside the timer routine.

 

c) Could this be tracemalloc overhead?   (the memory traces take memory space).  For example does the memory gets released with 

tracemalloc.clear_traces()  (tracemalloc — Trace memory allocations — Python 3.10.5 documentation)

 

d) Do you see Windows memory allocated to the process increasing without tracemalloc

Edited by pyscripter

Share this post


Link to post

a) YES without any code in __on_timer(...) I  have no memory leaks.
b) YES if I add any operations with a checkbox in __on_timer() the memory leaks begin.
c) I've used a const to DISABLE trace malloc os I can exclude that memory-leaks depends by it.
d) YES the graphical images posted are without the use of trace malloc but are a bird-eye view of the python windows process memory consumption.

In the test, I've checked only CheckBox.Enabled, to be simple, but in the full project, I've got some memory leaks also in <vcl>.Caption = etc.
The memory leaks began when I switched from PySimpleGUI to DelphiVCL UI.

The project uses a lot of DelphiVCL components so, in running time, the memory leak increases a lot.

A program, at first start, uses 139MB, but after two hours it reaches 700MB or memory usage and trace malloc suggests that is in DelphiVCL.

In the below video, I try to show the behavior.
The system is simple.

An embedded board with a camera, in this case, an RPI4, captures the camera frames and implements a server service to obtain an IP-CAMERA.
To simplify the case is written in Python.

A PC program, with Python + DelphiVCL + OpenCV + Skia connects to IP-Camera, gets frames, and applies code to elaborate it.

In the test code, I've added trace malloc with a first memory snapshot (take_snaphot) at the start.

When I press the middle button on the frame view I capture a memory snapshot that I compare with the start snapshot to show the top 10 memory consumers.

It is normal that no VCL objects reach temporary the top because I capture some frames and I take them for future uses but looking on the counter is low.

What I see is the usage memory and allocated counter increase continuously in some DelphiVCL operations.
To be honest, I don't know so wheel Python and inners, I've begun to use it some time ago to try to port some apps to Python language on customer request, I'm a Delphi developer.
So I can have mistakes on how to use tracemalloc to catch memory leaks.
 

https://www.youtube.com/watch?v=rhUniVnXgEQ

Edited by shineworld

Share this post


Link to post

This was due to a bug (TPyDelphiObject.SetAttrO causes memory leak · Issue #368 · pyscripter/python4delphi (github.com)) which is now fixed.   

 

It may take some time for the fix to be reflected in the pip installable delphivcl, but you can always compile your own delphivcl.pyd from the github sources.

 

@shineworldThanks for discovering the issue.

Edited by pyscripter
  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×