MilMike
MilMike

Reputation: 12831

Win32API causes memory leak

I am using the win32api to get a list of all window titles. I need the list to be refreshed every few seconds and thats the problem: The memory usage of the app is increasing every time I call EnumWindowsCallback.

Here is a working demo: Run the code and see in the task manager how the memory usage of this app increases. Press RETURN to call the function again.

Imports System.Runtime.InteropServices
Imports System.Text

Class Example
    Shared Sub Main()
        For a = 1 To 5
            Console.WriteLine("--------- (RUN NR " & a & ") PRESS RETURN")
            Console.ReadLine()
            Win32API.EnumWindowsDllImport(New Win32API.EnumWindowsCallback(AddressOf FillActiveWindowsList), 0)
        Next

        Console.WriteLine("READY!")
        Console.ReadLine()

    End Sub

    Shared Function FillActiveWindowsList(ByVal _hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean
        Dim windowText As New StringBuilder(255)        
        Win32API.GetWindowText(_hWnd, windowText, 255)
        Console.WriteLine(windowText)
        Return True
    End Function

End Class

Public Class Win32API
    Public Delegate Function EnumWindowsCallback(hWnd As Integer, lParam As Integer) As Boolean

    <DllImport("user32.dll", EntryPoint:="EnumWindows", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function EnumWindowsDllImport(callback As EnumWindowsCallback, lParam As Integer) As Integer
    End Function

    <DllImport("user32.dll", EntryPoint:="GetWindowTextA")> _
    Public Shared Sub GetWindowText(hWnd As Integer, lpstring As StringBuilder, nMaxCount As Integer)
    End Sub
End Class

at the beginning my EXE is about 3MB big, but after 5 function calls it is increased to 6 MB (and stays there) The problem is that it causes some crashes in my main application if the memory usage gets over 6 MB. The example above should not crash.

Do you see a problem here? Maybe there is a problem with the data types? or maybe it is a bug? Any help would be appreciated.

Upvotes: 0

Views: 510

Answers (2)

Omar AlMA3lOl
Omar AlMA3lOl

Reputation: 278

Replace This Code

For a = 1 To 5
    Console.WriteLine("--------- (RUN NR " & a & ") PRESS RETURN")
    Console.ReadLine()
    Win32API.EnumWindowsDllImport(New Win32API.EnumWindowsCallback(AddressOf FillActiveWindowsList), 0)
Next

with this code

dim a as integer = 1
DoitFive:
Console.WriteLine("--------- (RUN NR " & a & ") PRESS RETURN")
Console.ReadLine()
Win32API.EnumWindowsDllImport(New Win32API.EnumWindowsCallback(AddressOf FillActiveWindowsList), 0)
a += 1
if a <> 5 then goto DoitFive

Becouse the Code that you working with is holding the process of your EXE until loop 5 Times and that will make it 6MB Size.

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 941515

That's not possible, you won't get an OutOfMemoryException until you've consumed at least 1500 MB. You are a factor of x250 removed from explaining the "crash" with a leak. The 3 MB increase is simply the garbage collected heap growing to meet your program's demands. Seeing it stabilize is entirely normal as well, the ultimate hint that you don't have a leak.

Surely you get a better diagnostic than just "it crashed". You do have bugs in your code, the pinvoke declarations are wrong. The lParam arguments are IntPtr, not int. This can cause various amount of upheaval, you'd normally get a warning from the PInvokeStackImbalance Managed Debugger Assistant. Use the pinvoke.net website to get better ones. And do show in detail what that "crash" looks like in the debugger if you need more help.

Upvotes: 2

Related Questions