Solved

Memory eating api/variable help VB6

Posted on 2004-08-11
11
403 Views
Last Modified: 2013-11-13
The problem is the hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) Line is chewing up memory like crazy.  If I comment that line out problem goes away (but kills the process checker of course).  Is there a way to clear out the variable hSnap?  Tried the ways I know without success.  This code below is in a timer control.  HELP!!


Heres the code timer1 code:

  Dim f As Long, sname As String
         Dim hSnap As Long, proc As PROCESSENTRY32
         hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
         If hSnap = hNull Then Exit Sub
         proc.dwSize = Len(proc)

         ' Iterate through the processes
         f = Process32First(hSnap, proc)
         Do While f
               some code here
         f = Process32Next(hSnap, proc)
         Loop
           


Heres the module it uses:


      Public Declare Function Process32First Lib "kernel32" ( _
         ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

      Public Declare Function Process32Next Lib "kernel32" ( _
         ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

      Public Declare Function CloseHandle Lib "Kernel32.dll" _
         (ByVal Handle As Long) As Long

      Public Declare Function OpenProcess Lib "Kernel32.dll" _
        (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, _
            ByVal dwProcId As Long) As Long

      Public Declare Function EnumProcesses Lib "psapi.dll" _
         (ByRef lpidProcess As Long, ByVal cb As Long, _
            ByRef cbNeeded As Long) As Long

      Public Declare Function GetModuleFileNameExA Lib "psapi.dll" _
         (ByVal hProcess As Long, ByVal hModule As Long, _
            ByVal ModuleName As String, ByVal nSize As Long) As Long

      Public Declare Function EnumProcessModules Lib "psapi.dll" _
         (ByVal hProcess As Long, ByRef lphModule As Long, _
            ByVal cb As Long, ByRef cbNeeded As Long) As Long

      Public Declare Function CreateToolhelp32Snapshot Lib "kernel32" ( _
         ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

      Public Declare Function GetVersionExA Lib "kernel32" _
         (lpVersionInformation As OSVERSIONINFO) As Integer

      Public Type PROCESSENTRY32
         dwSize As Long
         cntUsage As Long
         th32ProcessID As Long           ' This process
         th32DefaultHeapID As Long
         th32ModuleID As Long            ' Associated exe
         cntThreads As Long
         th32ParentProcessID As Long     ' This process's parent process
         pcPriClassBase As Long          ' Base priority of process threads
         dwFlags As Long
         szExeFile As String * 260       ' MAX_PATH
      End Type

      Public Type OSVERSIONINFO
         dwOSVersionInfoSize As Long
         dwMajorVersion As Long
         dwMinorVersion As Long
         dwBuildNumber As Long
         dwPlatformId As Long           '1 = Windows 95.
                                        '2 = Windows NT

         szCSDVersion As String * 128
      End Type

      Public Const PROCESS_QUERY_INFORMATION = 1024
      Public Const PROCESS_VM_READ = 16
      Public Const MAX_PATH = 260
      Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
      Public Const SYNCHRONIZE = &H100000
      'STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
      Public Const PROCESS_ALL_ACCESS = &H1F0FFF
      Public Const TH32CS_SNAPPROCESS = &H2&
      Public Const hNull = 0
0
Comment
Question by:bluedragon99
11 Comments
 
LVL 1

Author Comment

by:bluedragon99
ID: 11777413
Hsnap is a Long btw
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 11777607
28 bytes of memory are being used everytime the timer runs by that line of code.  and it doesn't come back on exit.
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 11778456
also getting a bunch of squares appended on my processes variable, Ideas?
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 1

Author Comment

by:bluedragon99
ID: 11778533
 szExeFile As String * 260       ' MAX_PATH

in the module what the hell is the * 260 for?  its causing the garbage characters
0
 
LVL 3

Expert Comment

by:travisjhall
ID: 11779734
CreateToolhelp32Snapshot returns a handle to a snapshot, something that I'm not familiar with but which obviously uses a relatively large amount of memory. That snapshot will be maintained by the OS, and will probably be destroyed when all handles to it have been closed - that's usually how handles work.

So, are you closing the handle at some stage?
CloseHandle hSnap
or
If CloseHandle(hSnap) = 0 Then
  ' put some error checking code here because CloseHandle has failed - GetLastError API function should probably be involved
End If

Because I don't see something similar to that in what you have posted.
0
 
LVL 3

Expert Comment

by:travisjhall
ID: 11779761
BTW, CreateToolhelp32Snapshot won't return 0 when it fails. It returns INVALID_HANDLE_VALUE on failure. The definition is:
Public Const INVALID_HANDLE_VALUE = -1

You might like to add that line to your module in place of the hNull definition (or as well as, if hNull is used for other things), and change "If hSnap = hNull Then Exit Sub" to " If hSnap = INVALID_HANDLE_VALUE Then Exit Sub".

According to the Platform SDK, anyway.

When using API functions, the Platform SDK is your friend. Get it. Use it. Lots.
0
 
LVL 3

Expert Comment

by:travisjhall
ID: 11779825
The * 260 makes the string a fixed-length string of 260 characters. This results in the memory for those characters being allocated immediately, rather than as-needed like most strings in VB. Thus, when the API function works with this string, it has an appropiate buffer ready to receive its data. If you don't have this, the API function will try to overwrite a section of memory that isn't allocated for its use, because you haven't assigned the appropriate memory. Leave that "* 260" alone.

And the fixed-length nature of the string isn't causing the garbage characters. The garbage characters are just what happen to be used in the extra bytes of memory that aren't actually used by the API function. I'm guessing here, but I think you will find that at least the first of those "garbage characters" is a null character. If you need to work with the path of the exe file, you can do something to get the bit you want out of that string, like say:
Dim sExeFile As String
Dim lPos As Long
lPos = InStr(proc.sExeFile, vbNullChar)
If lPos = 0 Then
  sExeFile = proc.sExeFile
Else
  sExeFile = Left(proc.sExeFile, lPos)
End If

But I haven't tested that, so be a bit careful.
0
 
LVL 3

Accepted Solution

by:
Stimphy earned 250 total points
ID: 11780385
I have run your code and yes it does use memory... BUT I think if you just declare the variable type outside of the timer sub... your problems will go away.  I have run the code below with out the memory usage going up.

I believe that the allocated memory space for Proc is never deallocated with your code.  In the sample below, Proc is only defined once and is never defiined again.  Therefore, you dont get excessive memory usage.

'Try This:
'Top of Form

Dim Proc As PROCESSENTRY32

'Your Code...................

Private Sub Timer1_Timer()
 Dim f As Long, sname As String
         Dim hSnap As Long
         hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
         If hSnap = hNull Then Exit Sub
         proc.dwSize = Len(Proc)

         ' Iterate through the processes
         f = Process32First(hSnap, Proc)
         Do While f
               some code here
         f = Process32Next(hSnap, Proc)
         Loop
End Sub

Best Regaurds,
Dave
0
 
LVL 2

Expert Comment

by:amg42
ID: 11786733
From MSDN:

     To close a snapshot call the CloseToolhelp32Snapshot function.
     Do not call the CloseHandle function to close the snapshot call.
     Calling CloseHandle to close the snapshot call generates a memory leak.

So, maybe you can call CloseToolhelp32Snapshot(hSnap) after your Do...Loop?
0
 
LVL 3

Expert Comment

by:travisjhall
ID: 11789136
CloseHandle is the correct method of freeing memory allocated by CreateToolhelp32Snapshot under most versions of Windows. However, under Windows CE, CloseToolhelp32Snapshot is the correct method, and a memory leak will occur under Windows CE if you use CloseHandle instead. CloseToolhelp32Snapshot is only available under Windows CE, not any other OS.

In addition, a memory leak will occur using CreateToolhelp32Snapshot under Windows 2000 unless an appropriate hotfix is applied (or maybe that's been incorporated into a service pack by now? I don't know, I've lost track of how many win2K service packs are out). See http://support.microsoft.com/default.aspx?scid=kb;en-us;831712 for more details.
0
 
LVL 1

Author Comment

by:bluedragon99
ID: 11882066
It was the Dim'ing in the loop :)
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
A short article about a problem I had getting the GPS LocationListener working.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question