Could it be that this
DllCall(StrCat(DirWindows(1),"user32.dll"),long:"GetWindowRect", long:hwnd, lpbinary:lpRect)
bleeds a little strings memory every time around because I didn't use a DLL handle?
I know there's the DLLLoad function, but I never use it because there didn't seem to be any reason to. Could this be the reason?
TIA,
Kirby
Could it be that this
DllCall(StrCat(DirWindows(1),"user32.dll"),long:"GetWindowRect", long:hwnd, lpbinary:lpRect)
bleeds a little strings memory every time around because I didn't use a DLL handle?
I know there's the DLLLoad function, but I never use it because there didn't seem to be any reason to. Could this be the reason?
TIA,
Kirby
There are NO known memory leaks in the current version of WinBatch. However this particular API is passed a binary buffer lpRect. Do you have code that frees that buffer?
BinaryFree(lpRect)
I just did some testing using WinBatch 2013B on Windows 7 using the following code:
AddExtender("wwctl44i.dll")
window1=cWndByWndSpec("Shell_TrayWnd","explorer",2,303,40965)
window2=cWndByClass(window1,`TrayNotifyWnd`)
ControlHandle=cWndByClass(window2,`TrayClockWClass`)
BoxOpen('Infinite loop calling GetWindowRect','Open Resource Monitor or task Manager to see if there is any memory leaks in WinBatch.exe':@LF:@LF:'Press Ctrl+Break to end script')
While @True
; Fill buffer with control coordinates
rect = BinaryAlloc(16)
DllCall(StrCat(DirWindows(1), "User32.DLL"), long:"GetWindowRect", long:ControlHandle, lpbinary:rect)
xx = BinaryPeek4(rect, 0)
yy = BinaryPeek4(rect, 4)
BinaryFree(rect)
EndWhile
Exit
I was unable to reproduce any memory leak using the DllCall to GetWindowRect.
Can you confirm that you are Freeing all binary buffers using BinaryFree? Missing BinaryFree's can cause memory leaks.
Also I do not expect that this has anything to do with string memory being chewed up...Are you using very large strings or arrays that you are not 'Dropping' in your script?
Kirby,
Could it be that this
DllCall(StrCat(DirWindows(1),"user32.dll"),long:"GetWindowRect", long:hwnd, lpbinary:lpRect)
bleeds a little strings memory every time around because I didn't use a DLL handle?
These string literals are temporary objects. I would expect their memory to be freed as soon as the call returns. Regardless, when I need a string repeatedly, I define a script variable, named in upper case (following the style used for the C preprocessor constants defined in the headers that define much of the Windows API.
I know there's the DLLLoad function, but I never use it because there didn't seem to be any reason to. Could this be the reason?
Since user32.dll and kernel32.dll are auto-loaded into practically every process (certainly any GUI process, I've never called DllLoad on either of them. The only time I've needed DLLLoad is when I use my ancient (and deprecated) MD5 digest library, which requires a pair of calls in certain circumstances, the second of which reads data stored in a DWORD that lives in the address space of the DLL. Unless the DLL is loaded before the first call, and called through the handle both times, the second call always returns zero.
OK, further developments on this problem:
I have (exhaustively) reduced this program, eliminating functions, and watching the memory usage. I fully expected that I would remove some block of code or other and the leak would stop. Then I would find my mistake. But the leak did not stop.
Below is a forty-something line program that is, I believe, about as short as it can be and still do a callback dialog with timer. It exhibits the memory leak. According to my inexpert calculations, it leaks around 15 bytes per timer event.
I use a program called DebugView http://technet.microsoft.com/en-us/sysinternals/bb896647 (http://technet.microsoft.com/en-us/sysinternals/bb896647) to display my results using the DebugData statement, but you can replace that line with a Message statement to get the same results.
Question: what am I doing wrong?
-Kirby
Tick = 100 ; timer tick interval in milliseconds
memory = "" ; last memory status
#definesubroutine dlgcb(DH, DE, DC, undef1, Dextra)
switch 1
case DE == 0
DialogProcOptions(DH,1,Tick) ; timer ticks in milliseconds
DialogProcOptions(DH,2,@TRUE) ; accept push button
case DE == 1
z = intcontrol(77,0,0,0,0):'/':intcontrol(77,10,0,0,0):'/':intcontrol(77,30,0,0,0):'/':intcontrol(77,60,0,0,0)
if z != memory
DebugData('',"dbg: str/var/bb/com:": z )
memory = z
endif
break
case DE == 2
return 1
endswitch
return -1
#endsubroutine
MyDialogFormat=`WWWDLGED,6.2`
MyDialogCaption=`Menu`
MyDialogX=013
MyDialogY=066
MyDialogWidth=200
MyDialogHeight=355
MyDialogMinWidth=100
MyDialogMinHeight=200
MyDialogNumControls=002
MyDialogProcedure=`dlgcb`
MyDialogFont=`Microsoft Sans Serif|8192|40|34`
MyDialogTextColor=`0|0|0`
MyDialogBackground=`DEFAULT,DEFAULT`
MyDialogConfig=2
MyDialog001=`003,001,192,012,STATICTEXT,"st",DEFAULT,"Sales Menu",DEFAULT,20,1024,DEFAULT,DEFAULT,DEFAULT`
MyDialog002=`027,023,036,012,PUSHBUTTON,"push",DEFAULT,"OK",1,10,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
ButtonPushed=Dialog("MyDialog",1)
EXIT