Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tools to identify memory hogs in VB6 applications

What tools are available to attribute memory consumptions in VB6 application to it's multiple components? I can get the memory consumed by the entire application by watching various counters (Private Bytes, Working Set etc.), for example, in Process Explorer. I want to go level deeper than that and understand how much memory is consumed by various components or objects created at runtime. For example, figure out how much memory is consumed by large collection that's caching data at run time and how it changes based on number of elements in the collection.

like image 382
madearth Avatar asked Apr 13 '09 00:04

madearth


People also ask

How to find a memory leak in Visual Studio?

To find memory leaks and inefficient memory usage, you can use tools such as the debugger-integrated Memory Usage diagnostic tool or tools in the Performance Profiler such as the . NET Object Allocation tool and the post-mortem Memory Usage tool.

Which is used for memory usage analysis?

jvisualvm is one of the memory analysis tools for Java used to analyze the runtime behavior of a Java application. It traces a running Java program, checking its memory and CPU consumption. Also, it is used to create a memory heap dump to analyze the objects in the heap.


2 Answers

My favourite tool has to be DevPartner though at £1,500 a pop it is not cheap. It does a hell of a lot more than Memory leak checking though, but if that's all you need you might be carpet bombing ants.

If you want to see if your app is releasing resources correctly, use this Function I wrote to dump the memory at a given location. I would first cache the addresses of each of your variables then at shutdown you could call the DumpVariableMemory passing in references to those locations to see if they have been deallocated.

If you don't have one already, you'll need to add a declare fopr CopyMemory too :)

    Public Function DumpVariableMemory(ByVal lngVariablePointer&, _
                                   ByVal lngBufferSizeInBytes&) As String
    '' * Object Name:   DumpVariableMemory
    '' * Type:          Function
    '' * Purpose:       Returns a memory dump of the variable or pointer location
    '' * Created:       21/08/2006 - 17:41:32
    '' * Coder:         Richard Pashley - NUPUK00008148
    '' * Build Machine: W-XPRP-77
    '' * Encapsulation: Full
    '' * Parameters:    lngVariablePointer      -   Long    -   Pointer to the data to dump
    '' *                lngBufferSizeInBytes    -   Long    -   Size of the dump to ouput in bytes
    '' * Returns:       -                       -   String  -   Memory dump output as a string
    '' *                This will dump the memory location starting at the pointer address and
    '' *                ending at the address plus the offset (lngBufferSizeInBytes).
    '' *                You can use LenB to determine the size of the variable for the
    '' *                lngBufferSizeInBytes parameter if required.
    '' *                Example: DebugPrint DumpVariableMemory(VarPtr(lngMyLongValue),LenB(lngMyLongValue)
    '' * Modified By:   [Name]
    '' * Date:          [Date]
    '' * Reason:        [NUPUKxxxxxxxxx]
    '' Declare locals
    Dim lngBufferIterator&                  '' Buffer iterator
    Dim lngBufferInnerIterator&             '' Buffer loop inner iterator
    Dim bytHexDumpArray() As Byte           '' Received output buffer
    Dim strDumpBuffer$                      '' Formatted hex dump construction buffer
    Dim lngValidatedBufferSize&             '' Validated passed buffer size
    '' Turn on error handling
    On Error GoTo DumpVariableMemory_Err
    '' Resize output buffer
    ReDim bytHexDumpArray(0 To lngBufferSizeInBytes - 1) As Byte
    '' Retrieve memory contents from supplied pointer
    Call CopyMemory(bytHexDumpArray(0), _
       ByVal lngVariablePointer, _
       lngBufferSizeInBytes)
    '' Format dump header
    strDumpBuffer = String(81, "=") & vbCrLf & _
       "Pointer Address = &h" & Hex$(lngVariablePointer) & _
       "   Ouput Buffer Size = " & FormatBytes(lngBufferSizeInBytes)
    '' Add header seperator
    strDumpBuffer = strDumpBuffer & _
       vbCrLf & String(81, Chr$(61))
    '' Validate buffer dimensions
    If lngBufferSizeInBytes Mod 16 = 0 Then
        '' Validated ok so assign
        lngValidatedBufferSize = lngBufferSizeInBytes
    Else
        '' Refactor to base 16
        lngValidatedBufferSize = _
           ((lngBufferSizeInBytes \ 16) + 1) * 16
    End If
    '' Iterate through buffer contents
    For lngBufferIterator = 0 To (lngValidatedBufferSize - 1)
        '' Determine if first row
        If (lngBufferIterator Mod 16) = 0 Then
            '' Format dump output row
            strDumpBuffer = strDumpBuffer & vbCrLf & Right$(String(8, Chr$(48)) _
               & Hex$(lngVariablePointer + lngBufferIterator), 8) & Space(2) & _
               Right$(String(4, Chr$(48)) & Hex$(lngBufferIterator), 4) & Space(2)
        End If
        '' Determine required dump buffer padding
        If lngBufferIterator < lngBufferSizeInBytes Then
            '' Pad dump buffer
            strDumpBuffer = strDumpBuffer & Right$(Chr$(48) & _
               Hex(bytHexDumpArray(lngBufferIterator)), 2)
        Else
            '' Pad dump buffer
            strDumpBuffer = strDumpBuffer & Space(2)
        End If
        '' Determine required dump buffer padding
        If (lngBufferIterator Mod 16) = 15 Then
            '' Pad dump buffer
            strDumpBuffer = strDumpBuffer & Space(2)
            '' Iterate through buffer row
            For lngBufferInnerIterator = (lngBufferIterator - 15) To lngBufferIterator
                '' Validate row width
                If lngBufferInnerIterator < lngBufferSizeInBytes Then
                    '' Validate buffer constraints
                    If bytHexDumpArray(lngBufferInnerIterator) >= 32 And _
                       bytHexDumpArray(lngBufferInnerIterator) <= 126 Then
                        '' Ouput data to dump buffer row
                        strDumpBuffer = strDumpBuffer & _
                           Chr$(bytHexDumpArray(lngBufferInnerIterator))
                    Else
                        '' Pad dump buffer
                        strDumpBuffer = strDumpBuffer & Chr$(45)
                    End If
                End If
            Next
            '' Determine required dump buffer padding
        ElseIf (lngBufferIterator Mod 8) = 7 Then
            '' Pad dump buffer
            strDumpBuffer = strDumpBuffer & Chr$(45)
        Else
            '' Pad dump buffer
            strDumpBuffer = strDumpBuffer & Space(1)
        End If
    Next
    '' Assign result to function output
    DumpVariableMemory = strDumpBuffer & _
       vbCrLf & String(81, Chr$(61)) & vbCrLf
Exit_Point:
    Exit Function
    '' Error Handling
DumpVariableMemory_Err:
    LogError "modNYFixLibrary.DumpVariableMemory", Err.Number, Err.Description
    DumpVariableMemory = String(81, Chr$(61)) & vbCrLf & _
       "DumpFailed!" & vbCrLf & String(81, Chr$(61))
    GoTo Exit_Point
    Resume
End Function
like image 140
miPwn Avatar answered Sep 28 '22 09:09

miPwn


I'm not sure any publicly available (free) tools will profile VB6 code down to the module level. There are several memory profilers available for C/C++ and .NET, but not a lot on VB6 that I saw. Looks like all the old vendors (IBM Purify, Compuware Devpartner/Boundschecker) in this area have either been bought out, or moved on to .NET support only.

You might try GlowCode. It states C++ support, but also stresses Win32 native x86 images.

Microsoft publishes DebugDiag, which has support for memory leak detection for .NET, or Win32, though I've never used it with VB. It might not show outstanding allocations to the module level, but I'd bet it will at least attribute which libraries/dlls have allocated the most memory.

like image 26
Zach Bonham Avatar answered Sep 28 '22 10:09

Zach Bonham