Jump to content

Recommended Posts

Hi. I'm a teacher and I do a lot of tutorials and other presentations on my computer. I've developed a tool using AutoIt and Adobe AIR to display all the shortcuts I use while I'm presenting. According to the forum rules this would mean that I've developed a keylogger, so I can't show any of the code, but I'm still hoping someone will help me solve an issue I'm having - a memory leak (or at least I think that's it).

I can see the application is taking up more and more memory, but it never goes super crazy. I think it was at 25 MB at one point and that was it. However I see that the longer the application is running less responsive it is. It doesn't capture all the events, or it simply lags. 

I'm using AssocArrays and _MouseOnEvent UDFs, _WinAPI_SetTimer, _WinAPI_SetWindowsHookEx, _Singleton and TCP. I've done some research before posting this and I know there are some issues in special cases, but all solutions were "code specific". Since I can't post any of the code I couldn't respond in those threads. Other than that it really doesn't seem to be the problem with any of the UDFs, so my question is:

Is this a memory leak? If so how can I find it and remove it? What to do to avoid it in the future.

I understand that declaring variables over and over (something in the timer) may be the cause of this, so according to what I've read on the forum I've changed the variables to Global and moved them outside the functions. That way they are only declared once, and then only values are being reassigned. That unfortuantly didn't help. Is there anything else I could do or look for?

BTW - I've used Adobe AIR to create a nice UI. If someone want's to create something similar UEZ was kind enough to share his code of creating such GUI with nice antialiased labels. 
https://www.autoitscript.com/forum/topic/178366-adobe-air-like-window/#comment-1280587

screen.thumb.png.1a10abf83f1f825412b9f61

Link to comment
Share on other sites

A memory leak is when you permanently requesting resources without releasing these resources and the memory consumption for your exe is increasing constantly. A very good tool is ProcessExplorer from MS to find out for memory leaks.

If this applies to your code you have to check for resource consumption without releasing it.

E.g. if you call the function from the link you have posted (_GDIPlus_CreateCurvedTranslucentPanel) without releasing it

_GDIPlus_BitmapDispose($aReturn[0])

you will cause a memory leak.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Thanks for the answer. I do understand the basic concept and I was very careful when coding this. Even without being aware of memory leaks and what causes them I think it's a good programming habit to release resources - even just for clarity, so I am doing it. I fear that maybe there's something in the UDF's that is causing it (if it in fact is a memory leak). Then I notice something strange happening (like this lagging) I did notice that the app is still sending events over TCP at the exact time they should be send (probably because this is WinAPI hook that executes my function when the event happens), however a timer that is supposed to count down from last event is soooo far behind that it never sends the "clear" event (or whatever it is that it's suppose to be doing). When that happens memory consumption is about 25 MB but it never gets any higher. When I run the app fresh it's about 12MB. 

Also, aside from the timer I have a Do Untill WinActive("appname") loop (so that the app doesn't close) which checks is the Adobe AIR app is running, and if it doesn't the main code continues to run, which calls the _closeApp() (which clears resources).

;Wait for KeySnatcher to close or force stop by user
   Do
      Sleep(100)
   Until GUIGetMsg() = $GUI_EVENT_CLOSE or Not WinExists($hwndGui)
   _closeApp()

$hwndGui is a handle to the other app (the GUI made in Adobe AIR). So that then GUI is not running the app should close. The _closeApp() has a Beep function just for debug purposes. When I notice the lagging the app doesn't beep nor it shuts down. 

My intuition tells me there's something wrong with this loop. But what could it be? Could WinExists be the cause?

Below is everything that I can post without going into details of mouse / keyboard hooks. I'm not including any Global variables or other declarations that are above this code. As you can see I try to be as tidy and elegant with my coding to the best of my ability.

; ===========================================================
; Main Code
; ===========================================================
_Initialize()

Func _Initialize()

   ;Initialize TCP variables
   $sServer = "127.0.0.1"
   $sSocket = 0
   $sPort = 0

   ;Read settings from INI file
   $sPort = IniRead ( @ScriptDir & "\config.ini", "server", "port", "1007" )
   $cHotkey = IniRead ( @ScriptDir & "\config.ini", "control", "hotkey", "Ctrl + Alt + Shift + F12" )
   $hCmd = IniRead ( @ScriptDir & "\config.ini", "server", "hashcmd", "<::cmd>" )
   $iTimeOut = IniRead ( @ScriptDir & "\config.ini", "control", "timeout_ms", "3500" )
   Local $sServerAppTitle = IniRead ( @ScriptDir & "\config.ini", "server", "server_app_title", "KeySnatcher" )

   ;See if there's a KeySnatcher AIR app or another copy of THIS script running
   $hwndGui = WinActivate($sServerAppTitle)
   If $hwndGui = 0 or _Singleton($app, 1) = 0 Then
      Notify()
 ;few beeps
      Exit     ;exit - no resource were set yet, no need to free them
   Endif

   ;Set all variables to their default state (fresh start)
   _FreshStart()

   ;Try to connect to already running KeySnatcher (AIR) app
   ConnectToAirApp()

   ;Execute the core script
   _Run()
EndFunc

; PROCEDURE
; Establish a TCP connection with AIR server (KeySnatcher)
Func ConnectToAirApp()
   TCPStartup()
   Local $sIPAddress = $sServer
   Local $iPort = $sPort

   $sSocket = TCPConnect($sIPAddress, $iPort)

   If @error Then
      ; The server is probably offline/port is not opened on the server.
      Local $iError = @error
      MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), "Connect", "Could not connect, Error code: " & $iError)
      _close()
   Else
      debug("Connection succesful")
   EndIf
EndFunc   ;==>ConnectToAirApp

; PROCEDURE
; Create System Hooks and keep the script alive (infinite loop)
Func _Run()

   ;Creatre system hooks for keyboard and mouse: classes\sysHook.au3
   sysHook()

   ; Create a Timer to clear the display buffer after given time
   $iTimerID = _WinAPI_SetTimer(0, 0, $iTimerDelay, DllCallbackGetPtr($hTimerProc))

   ;System hooks created, timer set, ready to go
   Notify(True)

   ;Wait for KeySnatcher (AIR app) to close or force stop by user
   Do
      Sleep(100)
   Until GUIGetMsg() = $GUI_EVENT_CLOSE or Not WinExists($hwndGui)

   ;Close the script
   _Close()

EndFunc   ;==>_run

 

 

Link to comment
Share on other sites

How about the loop? Could WinExists cause this? Or maybe it's the fact that I have a Sleep(100) in that loop, and on top of that I have a _WinAPI Timer in my code as well. Maybe they get into some sort of a conflict? 

As for the UDFs - they come from the forum. I've posted what I use. As for _WinAPI functions I basically use examples from the AutoIt manual. All my code is just bunch of snippets working together (as it usually is). It's really hard to pinpoint. When the app is running, but I don't use my computer (so there's nothing to capture, but the timers are working) everything is fine. It can run for 12 hours and everything is fine. But when I'm presenting it takes about an hour for the app to start lagging. 

I've also noticed that when I do something CPU intensive (like presenting image processing or 3D rendering) the app cautpres few events at once, because "it did not manage" to show each action separately and it shows a couple all at once. Which should not happen. I've tripple checked the code. After each captured event, I send it via TCP to display, and after that I'm clearing the variable that holds what the action was, so if the app was unable to follow me in realtime it should at least show the first event that happened or the last, but not all at once. I don't get it. I tried to increase the priority to High with no effect. I am really lost.

Link to comment
Share on other sites

  • 2 weeks later...

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
 Share

×
×
  • Create New...