Hi. I have an issue with my app with opening a particular window and then closing it and each time this happens the object reference count increase by about 2000 and the memory consumption increases by about 60MB.
I’ve removed all the open and close code so the remaining code belongs to all the custom controls and their internal methods.
I am assuming that I’ve coded poorly and have created object references that cannot be destroyed (because they somehow link to other objects in memory) after the window closes, so can anyone give me some advice on how to use the Runtime classes such as ObjectCount and ObjectRef to determine what objects have been left behind after the window has closed so I can maybe track back and determine what I am doing wrong in their creation?
what is the scope of these objects?
if the “scope” is to the WINDOW you are closing, then they “should” be destroyed by virtue of the window closing…
HOWEVER… IF the window is “implicit instance” AND during the close process you reference ANYTHING related to that window, it will not leave the object count, and those object will remain. Then depending on how you instantiated them in the first place, they may duplcate when you next “open” the window (when in reality the window never was closed, it just became not visible)
Hi Dave. I am not familiar with ImplicitInstance but open the window by my window.show and don’t call anything on its close. So are you saying that because I have opened the window that way it doesn’t really close and destroy everything but instead just hides the window and keeps all of its object references?
Have you got code in your app that uses the AddHandler key word ? (literally search for “addHandler”)
If so, have you matched them with “RemoveHandler”
No… Windows are by default “Implicit Instance”… look at the property inspector of a window and you will see it.
Say for example you have a control on the window called “X”, and you close the window… This will raise the CLOSE event for that window IF for some reason (and this is just an example)… you have code in the CLOSE event that says
x.text="" // or anything else that refers to the window
an instance of this window is “implied” again, and it doesn’t “close”
One way to do it (which is lengthy) is to add “system.debugLog currentmethodName” to the constructor and destructor of each class, also give each object instance a UUID, so that you can write out which object is created and when it’s destroyed.
You could also store the object UUIDs in a dictionary on creation and remove them on destruction, this way you can display the contents of the dictionary after the window has long closed to see what’s still in memory.
In fact, I think I’m going to do that with my current project; which has almost a hundred classes.
I do this under a #IF DebugBuild THEN System.DebugLog "<method name> to all my apps these days. This way, I can see what the hell is going on when I am debugging it. And if I need to put in the production code, I do something like IF modVariables.Debug THEN System.DebugLog "<method name>. And just turn modVariables.Debug to True when I want the debugging.
You only need to notify this when you create an object, it uses weakRefs to monitor when an object goes out of scope. Items listed in green are new, items listed in red have gone out of scope (and are removed from the list on the next check).
[quote=348781:@Norman Palardy]Have you got code in your app that uses the AddHandler key word ? (literally search for “addHandler”)
If so, have you matched them with “RemoveHandler”
If not then this can cause memory leaks[/quote]
Yup, that was my problem, I had removeHandler on the destructor, but it wasn’t working (a custom rectControl class).
So now I use addhandler and removehandler only when needed.
If the object that’s raising the event is a property of the object that owns the handler method, then using AddressOf creates a circular reference between the two objects. RemoveHandler will break the circular reference, but the Destructor won’t run until after it’s broken.
After my brain unwrapped what you are saying; it was the case for that object, it had a timer property where AddHandler was used to patch the timer action event to a method on the object. So now it uses AddHandler only when the timer IS going to be used and the timer is not longer needed, removeHandler is called. Something I learned today; now I need to go back over my previous projects and I’m pretty certain that I’ve been making this mistake for a while.
[quote=348878:@Sam Rowlands]I ended up taking my own advice and created such a system for my current project, and lo discovered that I’m leaking a fairly critical object.
You only need to notify this when you create an object, it uses weakRefs to monitor when an object goes out of scope. Items listed in green are new, items listed in red have gone out of scope (and are removed from the list on the next check).[/quote]
Sam, you are a star! This really helped me track down the issue. The problem related to multiple instances of a custom class on the window that had a reference to its own dynamically created timer class. The timer class had a property “my owner” etc and this was held as a reference after the window closed for each custom control.
I had assumed that when the window closed the reference to the timer class was be nilled and in so doing the timer class instance itself would nil the object reference to its parent…but it didn’t so in the custom class close event I had to manually nil the timer instance that had been created on the open event.
Thank you for your help and for all the other advice I received.
[quote=348960:@Denise Adams]Sam, you are a star! This really helped me track down the issue. The problem related to multiple instances of a custom class on the window that had a reference to its own dynamically created timer class. The timer class had a property “my owner” etc and this was held as a reference after the window closed for each custom control.
I had assumed that when the window closed the reference to the timer class was be nilled and in so doing the timer class instance itself would nil the object reference to its parent…but it didn’t so in the custom class close event I had to manually nil the timer instance that had been created on the open event.
Thank you for your help and for all the other advice I received.[/quote]
On macOS the Instruments app can be handy for finding leaks also. (Xcode / Open Developer Tool / Instruments and then choose Leaks). It lets you track all allocations in an app and shows you the stack trace at the time of allocation, and has some heuristic for determining when an object has leaked. So if you think there’s a leak, just run your app for a while, then pause it and take a look at the leaking objects. It won’t tell you why the object wasn’t destroyed, but it’s very useful for figuring out what objects are leaking in the first place.
Use WeakAddressOf instead of AddressOf to prevent the circular reference from being created. This will behave much more like what you were expecting, and RemoveHandler becomes optional.
Excuse my ignorance but how can you check this? See this?
I’m using add handler a lot to web threads and just assumed they fixed themselves when the thread was cleaned up.
Ive never known how to check for memory leaks.
So I would really like to check this out.
Thanks for any help.