Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Trying To Understand Memory Cleanup Better

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
AntumDeluge
Cheater
Reputation: 0

Joined: 20 Dec 2018
Posts: 48

PostPosted: Thu Feb 14, 2019 4:35 am    Post subject: Trying To Understand Memory Cleanup Better Reply with quote

I have been coding/scripting for a few years now. But I have to admit that I often still don't understand completely how computers work & the proper way to do many things. One thing that I have always struggled with is freeing up memory properly & preventing memory leaks.

As I understand how Lua/CE work, when the closeCE() function is called, the main Cheat Engine processes is ended. But it does not handle any Forms I have created & they remain allocated in memory. I need to "destroy" them myself.

For example:
Code:
-- create a Form window
local form = createForm(false)

-- function to shutdown Cheat Engine
local function shutdown()
  -- free memory used by main window Form
  form.destroy() -- not sure if this is required here

  -- end CE process
  closeCE()
  return caFree
end

-- shutdown CE when Form window is closed
form.onClose = shutdown

-- show the Form window
form.show()


I also understand that if I create GUI elements that are children of the main Form, they are destroyed with it & their memory is freed up as well.

To amend the code above:
Code:
...

local panel = createPanel(form) -- this is cleaned up when main Form is destroyed

form.show()


One thing that I have done in the past is create a new Form as an about dialog. This dialog is created using a function called by a button or menu from the main Form. My understanding is that it is only in memory during the function's execution. Though, I am unsure if I need to call the destroy() method on it or if it is automatically freed. Example below:

Code:
...

-- function to show about dialog
local function showAbout()
  -- dialog window to show information about app
  local aboutDialog = createForm(false)
  aboutDialog.BorderStyle = bsDialog
  aboutDialog.setCaption("About")

  -- add a child panel to about dialog
  local aboutPanel = createPanel(aboutDialog)

  -- show dialog & disallow interaction with main Form while open
  aboutDialog.showModal()

  -- free memory allocated for dialog & its children
  aboutDialog.destroy() -- is this necessary here?
end

-- button to open about dialog
local buttonAbout = createButton(form)
buttonAbout.setCaption("About")
buttonAbout.onClick = showAbout

-- show the form window
form.show()


In the following case, I create the about dialog in the scope of the script rather than making it local to a function/method:
Code:
...

-- dialog window to show information about app
local aboutDialog = createForm(false)
aboutDialog.BorderStyle = bsDialog
aboutDialog.setCaption("About")

-- add a child panel to dialog
local aboutPanel = createPanel(aboutDialog)

-- function to show about dialog
local function showAbout()
  -- show dialog & disallow interaction with main Form while open
  aboutDialog.showModal()
end

...


If I do that, my understanding is that because the dialog is not a child of the main Form I need to free up its memory manually in the shutdown() function:

Code:
-- function to shutdown Cheat Engine
local function shutdown()
  -- free memory used by about dialog & its children
  aboutDialog.destroy()

  -- free memory used by main Form & its children
  form.destroy()

  -- close the CE process
  closeCE()
  return caFree
end


I believe that the above scripts should close cleanly. But I'm really not sure under what other circumstances I might need to manually free up memory.

Lua tables are handled by the Lua garbage collector when the process ends, correct? What happens if I create a form that is an element of a Lua table?

Code:
local about = {}
about.text = "About"
about.dialog = createForm(false)
about.dialog.BorderStyle = bsDialog
about.dialog.setCaption(about.text)


Do I still need to manually destroy it?

Code:
local function shutdown()
  -- free up memory used by about dialog
  about.dialog.destroy()

...


Any help in understanding all this is greatly appreciated. Memory allocation is an area where I struggle a lot.

Edit: To manually free memory allocated for variables & tables, I simply set their value to "nil"?

Code:
-- create a variable & table
local foo = "Hello world!"
local bar = {}

-- destroy variable & table freeing up memory
foo = nil
bar = nil


What happens to memory allocated for a Form that is an element of a table when that table's value is set to "nil"?

Code:
-- create a table
local foo = {}
foo.bar = createForm(false)

-- free table memory
foo = nil


Is it still in memory?

Edit: According to a garbage collection tutorial on lua-users.org, setting a variable/table to "nil" makes it "unreachable". So, that sounds to me like it is still in memory. And my guess is that the garbage collection process isn't executed until the Lua process exits?

So, if I truly want to free up memory during runtime, I need to call the collectgarbage() interface?

Code:
local foo = "Hello world!"
local bar = {}

-- make unreachable
foo = nil
bar = nil

-- free memory
collectgarbage()


And again, does this free up memory allocated for a Form as an element of a table?

Code:
local foo = {}
foo.bar = createForm(false)

-- make unreachable
foo = nil

-- free memory
collectgarbage()
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4300

PostPosted: Thu Feb 14, 2019 11:05 am    Post subject: This post has 1 review(s) Reply with quote

AntumDeluge wrote:
As I understand how Lua/CE work, when the closeCE() function is called, the main Cheat Engine processes is ended. But it does not handle any Forms I have created & they remain allocated in memory. I need to "destroy" them myself.
When a process is ended, Windows should automatically clean up most things belonging to that process, including all windows, forms, controls, etc. You don't need to destroy it yourself if you're closing the process. Just make sure you can't create infinitely many forms in the same process (e.g. every time a button is pressed, it creates a form that's never destroyed).

AntumDeluge wrote:
One thing that I have done in the past is create a new Form as an about dialog. This dialog is created using a function called by a button or menu from the main Form. My understanding is that it is only in memory during the function's execution. Though, I am unsure if I need to call the destroy() method on it or if it is automatically freed.
In that specific example, you should destroy the form because you're creating a new one every time showAbout is called. Ideally, you should create it once and show/hide it as needed, but this works too.

AntumDeluge wrote:
In the following case, I create the about dialog in the scope of the script rather than making it local to a function/method:
...
If I do that, my understanding is that because the dialog is not a child of the main Form I need to free up its memory manually in the shutdown() function:
...
As explained earlier, Windows should clean it up automatically when the process exits.

AntumDeluge wrote:
Lua tables are handled by the Lua garbage collector when the process ends, correct? What happens if I create a form that is an element of a Lua table?
The garbage collector runs incrementally and will clean up dead Lua objects. Every Lua object is handled by the garbage collector- not just tables. When no more names reference an object, the garbage collector can clean up the object. There are special rules for weak tables, but that's not relevant here.
AntumDeluge wrote:
To manually free memory allocated for variables & tables, I simply set their value to "nil"?
Setting a variable to nil destroys a reference to the underlying object. If that was the last reference to it, then the object is dead and it will be cleaned up by the garbage collector eventually.
AntumDeluge wrote:
What happens to memory allocated for a Form that is an element of a table when that table's value is set to "nil"?

Assuming there are no longer any references to the userdata object, it gets marked for cleanup by the garbage collector. The destroy function assigned to the userdata might be automatically called when garbage collected (see "__autodestroy" key in CE's source code). If it's not called and Lua garbage collects the userdata anyway, that might cause memory leak unless the underlying data is set up to free itself later (e.g. form OnClose returns caFree; thread freeOnTerminate is true).
AntumDeluge wrote:
According to a garbage collection tutorial on lua-users.org, setting a variable/table to "nil" makes it "unreachable". So, that sounds to me like it is still in memory. And my guess is that the garbage collection process isn't executed until the Lua process exits?

So, if I truly want to free up memory during runtime, I need to call the collectgarbage() interface?
The garbage collector is run automatically. You may need to make the garbage collector more aggressive, but you should never need to call collectgarbage() yourself (borderline perverse exceptions may exist).
This topic has a little more information. I don't know what the OP in that topic was doing, but I've never encountered a circumstance where memory allocation will outpace a garbage collector that's at least twice as aggressive as the default 200/200.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
AntumDeluge
Cheater
Reputation: 0

Joined: 20 Dec 2018
Posts: 48

PostPosted: Fri Feb 15, 2019 8:57 am    Post subject: Reply with quote

Thank you ParkourPenguin. That is all very informative & helpful. I'm sure I will have to come back to this thread to re-read some of what you wrote as I continue scripting. Smile

Super-tired at the moment.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites