Jump to content
Sign in to follow this  
kyuzumaki

Help with a memory leak..

Recommended Posts

kyuzumaki

Hi Guys,

I've been tearing my hair out over this one. Cant figure out where the leak is. When I run my script it will constantly increase in memory usage until it eventually crashes. When I watch the memory usage of autoit in the task manager there is no increase in usage but the overall usage drops as soon as i close my script.

Most of the code is very simple and by commenting out a single line I can stop the leak.. sadly this lines very important.

Heres the function i'm running which seems to be the problem. Its a modified version of a _tesseract.au3 function which simply captures an area of a window to a file and I've added code to rotate this image by 90 degrees before its saved.

EDIT: The memory usage increases quite rapidly about 12MB/min, the function is being called repeatedly in quick succession.

Func CaptureToTIFF($win_title = "", $win_text = "", $ctrl_id = "", $sOutImage = "", $scale = 1, $left_indent = 0, $top_indent = 0, $right_indent = 0, $bottom_indent = 0)

Local $hWnd, $hwnd2, $hDC, $hBMP, $hImage1, $hGraphic, $CLSID, $tParams, $pParams, $tData, $i = 0, $hImage2, $pos[4]
Local $Ext = StringUpper(StringMid($sOutImage, StringInStr($sOutImage, ".", 0, -1) + 1))
Local $giTIFColorDepth = 24
Local $giTIFCompression = $GDIP_EVTCOMPRESSIONNONE

; If capturing a control
if StringCompare($ctrl_id, "") <> 0 Then

$hwnd2 = ControlGetHandle($win_title, $win_text, $ctrl_id)
$pos = ControlGetPos($win_title, $win_text, $ctrl_id)
Else

; If capturing a window
if StringCompare($win_title, "") <> 0 Then

$hwnd2 = WinGetHandle($win_title, $win_text)
$pos = WinGetPos($win_title, $win_text)
Else

; If capturing the desktop
$hwnd2 = ""
$pos[0] = 0
$pos[1] = 0
$pos[2] = @DesktopWidth
$pos[3] = @DesktopHeight
EndIf
EndIf

; Capture an image of the window / control
if IsHWnd($hwnd2) Then

WinActivate($win_title, $win_text)
$size=WinGetClientSize($win_title,$win_text)
$hBitmap2 = _ScreenCapture_CaptureWnd("", $hwnd2, 0, 0, -1, -1, False)
Else

$hBitmap2 = _ScreenCapture_Capture("", $size[0], 0, 0, $size[1], False)
EndIf

;commented out and moved to start of code for debug _GDIPlus_Startup ()


$hImage2 = _GDIPlus_BitmapCreateFromHBITMAP ($hBitmap2)

$hWnd = _WinAPI_GetDesktopWindow()
$hDC = _WinAPI_GetDC($hWnd)
$hBMP = _WinAPI_CreateCompatibleBitmap($hDC, ($pos[2] * $scale) - ($right_indent * $scale), ($pos[3] * $scale) - ($bottom_indent * $scale))

_WinAPI_ReleaseDC($hWnd, $hDC)
$hImage1 = _GDIPlus_BitmapCreateFromHBITMAP ($hBMP)
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)
_GDIPLus_GraphicsDrawImageRect($hGraphic, $hImage2, 0 - ($left_indent * $scale), 0 - ($top_indent * $scale), ($pos[2] * $scale) + $left_indent, ($pos[3] * $scale) + $top_indent)

;removed tiff parameters settings for debug

; Save TIFF and cleanup
$hImage3 = _GDIPlus_BitmapCreateFromGraphics(_GDIPlus_ImageGetHeight($hImage1), _GDIPlus_ImageGetWidth($hImage1), $hGraphic)
$hGraphic3 = _GDIPlus_ImageGetGraphicsContext($hImage3)
$matrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixRotate($matrix, -90)
_GDIPlus_GraphicsSetTransform($hGraphic3, $matrix)
_GDIPlus_GraphicsDrawImage($hGraphic3, $hImage1, -_GDIPlus_ImageGetWidth($hImage1), 0)

_GDIPlus_ImageSaveToFile($hImage3, $sOutImage);, $CLSID, $pParams)
;replaced the below function call with code above for rotation to prevent nested starting of gdi plus
;rotate_image($sOutImage)
_GDIPlus_MatrixDispose($matrix)
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_ImageDispose($hImage2)
_GDIPlus_ImageDispose($hImage3)
_GDIPlus_GraphicsDispose ($hGraphic)
_GDIPlus_GraphicsDispose ($hGraphic3)
_WinAPI_DeleteObject($hBMP)
sleep(100)
;_GDIPlus_Shutdown()
EndFunc
Edited by kyuzumaki

Share this post


Link to post
Share on other sites
kyuzumaki

After posting I decided that I didn't trust _GDIPlus_Shutdown() or _GDIPlus_Startup() so I removed them entirely and executed them once at the beginning and end of the script. But no luck still getting the same issue out of ideas now.... :

Share this post


Link to post
Share on other sites
Danp2

I have experienced a similar memory leak while using GDIPlus. Here's my routine, which combines two images and saves them to a new file:

Func CombineImages()
$MergedImageBackgroundColor = 0x00000000 ;Specify 00 on first "digits" for transparent color (.png only !), all other values (......) will be ignored.

; Load image 1
$hImage1 = _GDIPlus_ImageLoadFromFile($frontDir & $sFront)
$iX1 = _GDIPlus_ImageGetWidth($hImage1)
If $iX1 = 4294967295 Then $iX1 = 0
$iY1 = _GDIPlus_ImageGetHeight($hImage1)

; Load image 2
$hImage2 = _GDIPlus_ImageLoadFromFile($backDir & $sBack)
$iX2 = _GDIPlus_ImageGetWidth($hImage2)
If $iX1 = 4294967295 Then $iX1 = 0
$iY2 = _GDIPlus_ImageGetHeight($hImage2)

; Name of destination image
$sDest = $combinedDir & StringReplace($sFront, "front_", "")

$height = $iY1 + $iY2
$width = _Max($iX1, $iX2)

; Initialise the Drawing windows/composite image...
$hGui = GUICreate("GDIPlus Example", $width, $height)

; Create Double Buffer, so the doesn't need to be repainted on PAINT-Event
$hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGui) ;Draw to this graphics, $hGraphicGUI, to display on GUI
$hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphicGUI) ; $hBMPBuff is a bitmap in memory
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff) ; Draw to this graphics, $hGraphic, being the graphics of $hBMPBuff

;Fill the Graphic Background (0x00000000 for transparent background in .png files)
_GDIPlus_GraphicsClear($hGraphic, $MergedImageBackgroundColor)

;Put the previously opened images together on the same Graphic and closing them
_GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage1, 0, 0, $iX1, $iY1, 0, 0, $iX1, $iY1)
_GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage2, 0, 0, $iX2, $iY2, 0, $iY1, $iX2, $iY2)
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_ImageDispose($hImage2)

ConsoleWrite($sDest & @CRLF)

; Save composite image (need that previously opened images have been closed if self-merging a file)
If Not _GDIPlus_ImageSaveToFile($hBMPBuff, $sDest) Then
ConsoleWrite("Error - " & $sDest & @CRLF)
EndIf

_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_GraphicsDispose($hGraphicGUI)
_WinAPI_DeleteObject($hBMPBuff)
GUIDelete ($hGui)
EndFunc

Share this post


Link to post
Share on other sites
kyuzumaki

Does your function produce a leak? Or did you solve it somehow? Its really frustrating because the program can only do about 2000 iterations before crashing i need it to do alot more

Is there an alternative to GDIPlus that will capture and rotate an image? I dont mind if its a bit slower as long as theres no memory leak

Edited by kyuzumaki

Share this post


Link to post
Share on other sites
FireFox

@kyuzumaki

You forgot to release this ressource :

_GDIPlus_BitmapDispose($hBitmap2)

Br, FireFox.


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites
FireFox

After posting I decided that I didn't trust _GDIPlus_Shutdown() or _GDIPlus_Startup()

Furthermore, it's clearly written in the help file that _GDIPlus_Shutdown does not release the ressources used with the GDIPlus functions :

You must dispose of all of your GDI+ objects before you call _GDIPlus_Shutdown


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites
kyuzumaki

Thanks FireFox that! I got a tool that tracks the GDI plus usage and it showed loads of bitmaps thats clearly the problem.

For some reason when I call the bitmap dispose method it crashes? Thoughts?

EDIT: Solved the screen capture is a HBitmap so you need to use the below line to dispose of it

_WinAPI_DeleteObject($hBitmap2)

Thanks!

Edited by kyuzumaki

Share this post


Link to post
Share on other sites
FireFox

EDIT: Solved the screen capture is a HBitmap

Yes right I was misled by the var name.

 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites
Danp2

Does your function produce a leak? Or did you solve it somehow? Its really frustrating because the program can only do about 2000 iterations before crashing i need it to do alot more

I haven't run this routine in a while, but I believe I was experiencing the same issue where it crashed after a limited number of iterations.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×