Jump to content
Sign in to follow this  
lsakizada

memory leak in my application

Recommended Posts

lsakizada

I have created a tool to monitor proccesses. The tool is working fine except for one issue. After 3-4 hours the memory of the application

is growing. I could not find a reason why the memory leak. The memory is leaking only when running the application.

can you please help me to fix the problem?

The files are locating on this thread: click here

To see the problem:

Compile the MonMon.au3 after

1) type a proccess name : lets say svschost.exe for example.

Note: You can monitor the monmon.exe

2) Click on Update button.

3) Click on the Upper/left button to start monitoring the proccess.

keep that tool running couple hour.

Notice that the while loop is handling the monitor proccess.

Please help...


Be Green Now or Never (BGNN)!

Share this post


Link to post
Share on other sites
Zedna

I quickly looked at your main script and it looks OK.

Try to isolate your problem code.

Eliminating method - remove some parts of code and look if it helps solve problem. This way you can find problem part of your code.

Then make SIMPLE reproducing script and post your question here again.

Share this post


Link to post
Share on other sites
lsakizada

I quickly looked at your main script and it looks OK.

Try to isolate your problem code.

Eliminating method - remove some parts of code and look if it helps solve problem. This way you can find problem part of your code.

Then make SIMPLE reproducing script and post your question here again.

Thanks for the reply.

The While loop that handle the monitoring is responsible to the memory leak.

I guess the memory leak is an autoit problem. I COULD NOT FIND IT.

please look at the loop, it does not do much....thougt.


Be Green Now or Never (BGNN)!

Share this post


Link to post
Share on other sites
Siao

It's quite easy to deduct that the leak is caused by _ProcessListProperties(), or to be more exact, all that WMI object stuff. "WbemScripting.SWbemRefresher" part leaks more, "winmgmts" less.

I don't know much about WMI, maybe there's some proper methods of disconnecting from it or whatever else you are not doing.

Assigning 0 to all the object variables after each of the loops doesn't seem to help any.

The code overall could be improved in many ways.


"be smart, drink your wine"

Share this post


Link to post
Share on other sites
lsakizada

It's quite easy to deduct that the leak is caused by _ProcessListProperties(), or to be more exact, all that WMI object stuff. "WbemScripting.SWbemRefresher" part leaks more, "winmgmts" less.

I don't know much about WMI, maybe there's some proper methods of disconnecting from it or whatever else you are not doing.

Assigning 0 to all the object variables after each of the loops doesn't seem to help any.

The code overall could be improved in many ways.

Hi Sciao, thanks for the reply.

I saw that I missed cleeaning the Refresher object.

I am adding this code then I will see if it is helps:

If IsObj($oRefresher) Then

$oRefresher = ""

EndIf

I agree that the code could be improved in many ways, i created it in few days for my needs only, I will post version 2 with more functionality and better code.

I will update regards the memory leak.


Be Green Now or Never (BGNN)!

Share this post


Link to post
Share on other sites
lsakizada

here is where the memory leak came from: How to fix it please...

#include <GUIConstants.au3>

HotKeySet("{Esc}", "HotKey")
While 1
    _ProcessListProperties()
WEnd

Func HotKey()
        Switch @HotKeyPressed
            Case  "{Esc}"
                exit
        EndSwitch
EndFunc  
Func _ProcessListProperties($Process = "", $sComputer = ".")
    Local $sUserName, $sMsg, $sUserDomain, $avProcs
    If $Process = "" Then
        $avProcs = ProcessList()
    Else
        $avProcs = ProcessList($Process)
    EndIf
    If $avProcs[0][0] = 0 Then Return $avProcs
    ReDim $avProcs[$avProcs[0][0] + 1][40]
    $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")
    If IsObj($oWMI) Then
        $colProcs = $oWMI.ExecQuery("select * from win32_process")
        If IsObj($colProcs) Then
            For $oProc In $colProcs
                For $n = 1 To $avProcs[0][0]
                    If $avProcs[$n][1] = $oProc.ProcessId Then
                        $avProcs[$n][2] = $oProc.ParentProcessId
                        If $oProc.GetOwner($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName
                        $avProcs[$n][4] = $oProc.Priority
                        $avProcs[$n][5] = $oProc.ExecutablePath
                        $avProcs[$n][8] = $oProc.CommandLine
                        $avProcs[$n][9] = __StringToDate($oProc.CreationDate)
                        $avProcs[$n][10] = $oProc.Description
                        $avProcs[$n][11] = $oProc.ExecutionState
                        $avProcs[$n][12] = $oProc.Handle
                        $avProcs[$n][13] = $oProc.HandleCount
                        $avProcs[$n][14] = $oProc.KernelModeTime
                        $avProcs[$n][15] = $oProc.MaximumWorkingSetSize
                        $avProcs[$n][16] = $oProc.MinimumWorkingSetSize
                        $avProcs[$n][17] = $oProc.OSName
                        $avProcs[$n][18] = $oProc.OSCreationClassName
                        $avProcs[$n][19] = $oProc.OtherOperationCount
                        $avProcs[$n][20] = $oProc.OtherTransferCount
                        $avProcs[$n][21] = $oProc.PageFaults
                        $avProcs[$n][22] = $oProc.PageFileUsage
                        $avProcs[$n][23] = $oProc.PeakPageFileUsage
                        $avProcs[$n][24] = $oProc.PeakVirtualSize
                        $avProcs[$n][25] = $oProc.PrivatePageCount
                        $avProcs[$n][26] = $oProc.QuotaNonPagedPoolUsage
                        $avProcs[$n][27] = $oProc.QuotaPagedPoolUsage
                        $avProcs[$n][28] = $oProc.QuotaPeakNonPagedPoolUsage
                        $avProcs[$n][29] = $oProc.QuotaPeakPagedPoolUsage
                        $avProcs[$n][30] = $oProc.ReadOperationCount
                        $avProcs[$n][31] = $oProc.ReadTransferCount
                        $avProcs[$n][32] = $oProc.SessionId
                        $avProcs[$n][33] = $oProc.Status
                        $avProcs[$n][34] = $oProc.ThreadCount
                        $avProcs[$n][35] = $oProc.UserModeTime
                        $avProcs[$n][36] = $oProc.VirtualSize
                        $avProcs[$n][37] = $oProc.WindowsVersion
                        $avProcs[$n][38] = $oProc.WriteOperationCount
                        $avProcs[$n][39] = $oProc.WriteTransferCount
                        ExitLoop
                    EndIf
                Next
            Next
        Else
            SetError(2)
        EndIf
        Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher")
        $colProcs = $oRefresher.AddEnum($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet
        $oRefresher.Refresh
        Local $iTime = TimerInit()
        Do
            Sleep(10)
        Until TimerDiff($iTime) > 100
        $oRefresher.Refresh
        For $oProc In $colProcs
            For $n = 1 To $avProcs[0][0]
                If $avProcs[$n][1] = $oProc.IDProcess Then
                    $avProcs[$n][6] = $oProc.PercentProcessorTime
                    $avProcs[$n][7] = $oProc.WorkingSet
                    ExitLoop
                EndIf
            Next
        Next
    Else
        SetError(1)
    EndIf
    If IsObj($oWMI) Then
        $oWMI = ""
    EndIf
    
    If IsObj($oRefresher) Then
        $oRefresher = ""
    EndIf
    
    Return $avProcs
EndFunc;==>_ProcessListProperties

Func __StringToDate($dtmDate)
    Return (StringMid($dtmDate, 5, 2) & "/" & _
            StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
             & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc;==>__StringToDate
Edited by lsakizada

Be Green Now or Never (BGNN)!

Share this post


Link to post
Share on other sites
ChrisL

This isn't really the answer but might help

#include <GUIConstants.au3>

HotKeySet("{Esc}", "HotKey")

Global $iTimer = TimerInit()
Global $iRestartTimer = 30;seconds

While 1
  _ProcessListProperties()
WEnd

Func HotKey()
        Switch @HotKeyPressed
            Case  "{Esc}"
                exit
        EndSwitch
EndFunc  
Func _ProcessListProperties($Process = "", $sComputer = ".")
    
    If TimerDiff($iTimer) >= $iRestartTimer * 1000 then 
;I don't think killing WMI really helped
;ConsoleWrite("Restart WMI" & @crlf) 
;RunWait ("winmgmt /kill","",@SW_Hide)
;RunWait ("Net start winmgmt","",@SW_Hide)
        ConsoleWrite("Reduce memory" & @crlf)
        _ReduceMemory(@AutoItPID)
        $iTimer = TimerInit()
    EndIf
    
    Local $sUserName, $sMsg, $sUserDomain, $avProcs , $oRefresher
    If $Process = "" Then
        $avProcs = ProcessList()
    Else
        $avProcs = ProcessList($Process)
    EndIf
    
    If $avProcs[0][0] = 0 Then Return $avProcs
    ReDim $avProcs[$avProcs[0][0] + 1][40]
            
    $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")

    If IsObj($oWMI) Then

        $colProcs = $oWMI.ExecQuery("select * from win32_process")
        If IsObj($colProcs) Then
            For $oProc In $colProcs
                
                For $n = 1 To $avProcs[0][0]
                    If $avProcs[$n][1] = $oProc.ProcessId Then
                        $avProcs[$n][2] = $oProc.ParentProcessId
                        If $oProc.GetOwner($sUserName, $sUserDomain) = 0 Then $avProcs[$n][3] = $sUserDomain & "\" & $sUserName
                        $avProcs[$n][4] = $oProc.Priority
                        $avProcs[$n][5] = $oProc.ExecutablePath
                        $avProcs[$n][8] = $oProc.CommandLine
                        $avProcs[$n][9] = __StringToDate($oProc.CreationDate)
                        $avProcs[$n][10] = $oProc.Description
                        $avProcs[$n][11] = $oProc.ExecutionState
                        $avProcs[$n][12] = $oProc.Handle
                        $avProcs[$n][13] = $oProc.HandleCount
                        $avProcs[$n][14] = $oProc.KernelModeTime
                        $avProcs[$n][15] = $oProc.MaximumWorkingSetSize
                        $avProcs[$n][16] = $oProc.MinimumWorkingSetSize
                        $avProcs[$n][17] = $oProc.OSName
                        $avProcs[$n][18] = $oProc.OSCreationClassName
                        $avProcs[$n][19] = $oProc.OtherOperationCount
                        $avProcs[$n][20] = $oProc.OtherTransferCount
                        $avProcs[$n][21] = $oProc.PageFaults
                        $avProcs[$n][22] = $oProc.PageFileUsage
                        $avProcs[$n][23] = $oProc.PeakPageFileUsage
                        $avProcs[$n][24] = $oProc.PeakVirtualSize
                        $avProcs[$n][25] = $oProc.PrivatePageCount
                        $avProcs[$n][26] = $oProc.QuotaNonPagedPoolUsage
                        $avProcs[$n][27] = $oProc.QuotaPagedPoolUsage
                        $avProcs[$n][28] = $oProc.QuotaPeakNonPagedPoolUsage
                        $avProcs[$n][29] = $oProc.QuotaPeakPagedPoolUsage
                        $avProcs[$n][30] = $oProc.ReadOperationCount
                        $avProcs[$n][31] = $oProc.ReadTransferCount
                        $avProcs[$n][32] = $oProc.SessionId
                        $avProcs[$n][33] = $oProc.Status
                        $avProcs[$n][34] = $oProc.ThreadCount
                        $avProcs[$n][35] = $oProc.UserModeTime
                        $avProcs[$n][36] = $oProc.VirtualSize
                        $avProcs[$n][37] = $oProc.WindowsVersion
                        $avProcs[$n][38] = $oProc.WriteOperationCount
                        $avProcs[$n][39] = $oProc.WriteTransferCount
                        ExitLoop
                    EndIf
                Next
            Next
        Else
            SetError(2)
        EndIf
        Local $oRefresher = ObjCreate("WbemScripting.SWbemRefresher")
        $colProcs = $oRefresher.AddEnum($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet
        $oRefresher.Refresh
        Local $iTime = TimerInit()
        Do
            Sleep(10)
        Until TimerDiff($iTime) > 100
        $oRefresher.Refresh
        For $oProc In $colProcs
            For $n = 1 To $avProcs[0][0]
                If $avProcs[$n][1] = $oProc.IDProcess Then
                    $avProcs[$n][6] = $oProc.PercentProcessorTime
                    $avProcs[$n][7] = $oProc.WorkingSet
                    ExitLoop
                EndIf
            Next
        Next
    Else
        SetError(1)
    EndIf
    If IsObj($oWMI) Then
        $oWMI = ""
    EndIf
    
    If IsObj($oRefresher) Then
        $oRefresher = ""
    EndIf
    
    Return $avProcs
EndFunc;==>_ProcessListProperties

Func __StringToDate($dtmDate)
    Return (StringMid($dtmDate, 5, 2) & "/" & _
            StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
             & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate, 13, 2))
EndFunc;==>__StringToDate
         
Func _ReduceMemory($i_PID = -1)
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf
    
    Return $ai_Return[0]
EndFunc

I noticed that as soon as you do this

$oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")

the memory shoots up and if you reset the variable$oWMI = 0 and return straight away the memory still keeps climbing

So changing the function to this still makes the memory shoot up

Func _ProcessListProperties($Process = "", $sComputer = ".")
    $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sComputer & "\root\cimv2")
    $oWMI = 0
    Return 
Endfunc

This line also makes the memory go up but not come down

$colProcs = $oRefresher.AddEnum($oWMI, "Win32_PerfFormattedData_PerfProc_Process" ).objectSet;this makes the memory increase too
Edited by ChrisL

Share this post


Link to post
Share on other sites
lsakizada

This line also makes the memory go up but not come down

Yes I just found that Microsoft published that WMI has memory leak when calling it fast enough..

But i could not find fix for it.

From Microsofot site:

[quote]When you run a program that uses the Windows Management Instrumentation (WMI) service in Microsoft Windows XP, the memory that is used by a remote procedure call (RPC) cache may not be freed, and a memory leak may occur. The RPC cache may grow so large that it causes the program and Windows XP to become unresponsive.[/quote]

here is the link to Microsoft site:


Be Green Now or Never (BGNN)!

Share this post


Link to post
Share on other sites
ChrisL

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  

×