News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

MemProof and MASM = Memory leak/issues ...

Started by James Ladd, July 24, 2005, 04:12:01 AM

Previous topic - Next topic

James Ladd

When using memproof a lot of issues were reported on my code.
Then I thought, hey Ill cut back to something simple and see if the "issues" are in my code or in the
libraries I include. When I have this code

.data
    szRunning db 13,10,"Running...",0
.code
start:
    invoke StdOut, addr szRunning
    invoke ExitProcess, eax
end start


and I run memproof on this, I get messages about "GetStdHandle"
eg: "The returned handle must be freed with CloseHandle when no longer needed"

Is there some palce to report this sort of thing for MASM and more importantly, will someone
fix this sort of issue ?

Rgs, striker.

MichaelW

#1
StdOut calls GetStdHandle, which retrieves an existing handle that the system created during console creation. In the MSDN documentation for the GetStdHandle function there is no reference to closing the handle, and the example code does not close the handle.

MSDN: Console Handles

MSDN: GetStdHandle

EDIT:
Testing with the management console under Windows 2000, the test app below had no effect on the handle count for the app's process, or the total handle count for all processes.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    mov   eax, input(13,10,"Press enter to start test...")
    mov   ebx,10000000
  @@:
    invoke GetStdHandle, STD_OUTPUT_HANDLE
    .IF (eax == INVALID_HANDLE_VALUE)
        print "INVALID_HANDLE_VALUE",13,10
        jmp   @F
    .ENDIF
    dec   ebx
    jnz   @B
  @@:
    mov   eax, input(13,10,"Press enter to exit...")
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

eschew obfuscation

hutch--

James,

One of the things I have seen over time is the failure of memory leak detection software in enough instances. I don't trust them and I don't use them for this reason, nothing beats closing what you open or deallocating what you allocate, testing the return value and doing exactly what Michael has done, look at the count.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Mark Jones

I think that MemProof is too aggressive sometimes, but then again it's designed to be. It is also designed for C code and not MASM, unsure of the full ramifications that imposes. You can turn off "Error on Invalid Free" under Configure-->Settings though, but as others have pointed out it might be best to test all handles first and only free the ones which exist, lest Windows change in the future and your program crashes trying to free invalid/null handles... :toothy

I think this issue with GetStdHandle is a unique one. I've used MemProof a lot (for GUI apps) and it's been spot-on so far. The Win32.hlp file doesn't say anything about freeing GetStdHandle, Michael is correct there. The MemProof devs don't support MemProof any longer either, so asking for a bugfix would be pointless. I'd wager that this issue does not exist in their commercial software line though. http://www.automatedqa.com/
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

James Ladd

Thanks for the replies all !

I agree with you Hutch, that nothing beats doing the deallocation/close yourself.
However, this isnt the case with StdOut. Can you fix it ?

Rgs, striker.

hutch--

James,

The API in question,


invoke GetStdHandle,STD_OUTPUT_HANDLE


does not allocate a handle but obtains an EXISTING handle for STD_OUTPUT so it is a mistake to try and delete it after use. The leak detecion software you are using is defective here. The system would probably ignore an atempt to delete it but you could just be lucky enough for the next dork at Microsoft to read the spec the wrong way and drop an exception if it was.

Reference is both PLATFORMSDK and the original WIN32.HLP.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Biterider

Hi,
I found this in the NSDN documentation http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/closehandle.asp

Remarks
The CloseHandle function closes handles to the following objects:
...
Console input
Console screen buffer
...

Biterider

hutch--


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getstdhandle.asp

"The GetStdHandle function retrieves a handle for the standard input, standard output, or standard error device."
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Biterider

#8
Hi
I have written a small app to check some things.
First, after calling GetStdHandle to retrieve a STD_INPUT_HANDLE I call GetHandleInformation to inspect the Object handle flags. I this case it returns 1, that means that it is not protected from the CloseHandle api. Next, I call CloseHandle and check its return value. It returns TRUE!

When I repeat this a second time, I get the SAME handle value with its flags set to 3, calling CloseHandle fails and any use of this handle has no effect. The handle was definitively altered or closed!

Now repeating all again without closing the handle, all works normally.

It seems that the OS creates the STD_XXX handles when it creates the console and GetStdHandle only retrieves this value without duplicating it.
I assume the OS closes the STD_XXX handles when the console are closed.

Here the code I used:

    ...
    DbgText " "
    DbgText "Press \[ENTER\] to continue..."
    invoke GetStdHandle, STD_INPUT_HANDLE
    DbgHex eax
    push eax

    push eax
    invoke GetHandleInformation, eax, esp
    pop eax
    DbgHex eax

    invoke SetConsoleMode, [esp + 4], ENABLE_LINE_INPUT

    push eax
    invoke ReadFile, [esp + 20], esp, 4, NULL, NULL
    pop eax

    pop eax
;    invoke CloseHandle, eax
;    DbgHex eax

    DbgLine

    DbgText " "
    DbgText "Press \[ENTER\] to continue..."
    invoke GetStdHandle, STD_INPUT_HANDLE
    DbgHex eax
    push eax

    push eax
    invoke GetHandleInformation, eax, esp
    pop eax
    DbgHex eax

    invoke SetConsoleMode, [esp + 4], ENABLE_LINE_INPUT

    push eax
    invoke ReadFile, [esp + 20], esp, 4, NULL, NULL
    pop eax

    pop eax
;    invoke CloseHandle, eax
;    DbgHex eax
    ...


Regards,

Biterider


hutch--

Biterider,

Thanks for writing the test, it supports the documentation for the API. I have been too busy but the type of test I would use to test a handle leak would be to run the task manager and a console app that was streaming console output at the same time and watch the handle count as it was running. It is actually a good technique for this type of problem and you will see the handle count rocket if its leaking.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

MichaelW

I modified my previous code to verify that GetStdHandle returns the same handle each time it is called (on my system the value was 7).

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
        hStdOut dd 0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    mov   eax, input(13,10,"Press enter to start test...")
    mov   ebx,100000000
  @@:
    invoke GetStdHandle,STD_OUTPUT_HANDLE   
    .IF (eax == INVALID_HANDLE_VALUE)
        print "INVALID_HANDLE_VALUE",13,10
        jmp   @F
    .ENDIF
    .IF (hStdOut)
        .IF (hStdOut != eax)
            print "value not duplicate",13,10P
            jmp   @F
        .ENDIF
    .ELSE
        mov   hStdOut, eax
        print uhex$(eax),'h',13,10
    .ENDIF
    dec   ebx
    jnz   @B
  @@:
    mov   eax, input(13,10,"Press enter to exit...")
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start

eschew obfuscation