Delphi Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming Languages - MoreDelphi Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old November 27th, 2005, 03:02 PM
techie007 techie007 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2005
Posts: 3 techie007 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 28 m 10 sec
Reputation Power: 0
Result:TBitmap Memory Leak???

Ok this is driving me nutso

I am trying to capture the client area of a window and have it returned as a bitmap.

The idea is to put it in a 1 second timer.

Here's code that is similar to what I'm trying to do (it's just been edited to make it usable by others who want to test it) and it shows the leak (you can watch it eat it up in the Task Manager, until it crashes).

It takes 30-60 seconds to start leaking on my machine. Making the timer faster (ie: 500ms) makes it leak quicker as well.

If I don't assign values to the Result.Width and Result.Height properties it doesn't leak; and the smaller/larger you make them it directly affects how fast the memory leaks. Obviously a 0x0 resulting bitmap isn't much use.

It's like I need to free the result after I'm done with it, but I don't know how I can do that and still pass it back to the caller?

How can I do this and not have it leak? Any ideas are appreciated.

Thanks in advance!

Code:
Unit projleaktest;

Interface

Uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

Type
  TForm1 = Class(TForm)
    Timer1: TTimer;
    Image1: TImage;
    Procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  End;

Var
  Form1: TForm1;
  TheHandle: Integer;

Implementation

{$R *.dfm}

Function CaptureScreen: TBitmap;
Var
  DC: HDC;
Begin
  DC := GetDC(TheHandle);
  Try
    Result := TBitmap.Create;
    Try
      Result.Width := 600;
      Result.Height := 500;
      BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, DC, 0, 0,
        SRCCOPY);
      Result.Modified := True;
    Finally
      ReleaseDC(TheHandle, DC);
    End;
  Except
    Result.Free;
    Result := Nil;
  End;
End;

Procedure TForm1.Timer1Timer(Sender: TObject);
Begin
  TheHandle := 0;
  image1.Picture.Bitmap := CaptureScreen;
End;

End.

Reply With Quote
  #2  
Old November 28th, 2005, 10:42 AM
M.Hirsch M.Hirsch is offline
Contributing User
Dev Shed God 1st Plane (5500 - 5999 posts)
 
Join Date: Oct 2000
Location: Back in the real world.
Posts: 5,969 M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 1 Month 1 Day 22 h 42 m 50 sec
Reputation Power: 185
TBitmap is using a windows system bitmap internally. So it's not only a memory leak but even resources. After some hours your PC will lock completely.

If you want to return a TBitmap from a function, the caller has to free it later.

(edit)
Sorry, stupid code removed.
Use a temporary variable to store the bitmap reference before assigning it to the bitmap. Then you can use:
if Assigned(tmpBitmap) then tmpBitmap.Free;
tmpBitmap:=CaptureScreen;

M.
__________________
--
Manuel Hirsch - Linux, FreeBSD, programming, administration articles, tutorials and more.

Reply With Quote
  #3  
Old November 28th, 2005, 12:16 PM
techie007 techie007 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2005
Posts: 3 techie007 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 28 m 10 sec
Reputation Power: 0
Quote:
Originally Posted by M.Hirsch
Use a temporary variable to store the bitmap reference before assigning it to the bitmap. Then you can use:
if Assigned(tmpBitmap) then tmpBitmap.Free;
tmpBitmap:=CaptureScreen;


Hi, and thanks for the responce!

So I'd be aiming to do this(?):

Code:
Procedure TForm1.Timer1Timer(Sender: TObject);
var
  tmpBitMap: TBitmap
Begin
  TheHandle := 0;
  if Assigned(tmpBitmap) then tmpBitmap.Free;
  tmpBitmap:=CaptureScreen;
  image1.Picture.Bitmap := tmpBitmap;
End;

Reply With Quote
  #4  
Old November 28th, 2005, 01:08 PM
M.Hirsch M.Hirsch is offline
Contributing User
Dev Shed God 1st Plane (5500 - 5999 posts)
 
Join Date: Oct 2000
Location: Back in the real world.
Posts: 5,969 M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level)M.Hirsch User rank is First Lieutenant (10000 - 20000 Reputation Level) 
Time spent in forums: 1 Month 1 Day 22 h 42 m 50 sec
Reputation Power: 185
Yes. Only that "tmpBitmap" has to be persistent between calls of Timer1Timer which a local variable isn't. Add it to the private declarations of your form or outside of the function declaration (move it just above "Procedure...", this is fine IMO since this makes it a unit-local variable and not a global).

HTH,
M.

Reply With Quote
  #5  
Old November 29th, 2005, 09:30 AM
techie007 techie007 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Nov 2005
Posts: 3 techie007 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 28 m 10 sec
Reputation Power: 0
Quote:
Originally Posted by M.Hirsch
Yes. Only that "tmpBitmap" has to be persistent between calls of Timer1Timer which a local variable isn't. Add it to the private declarations of your form or outside of the function declaration (move it just above "Procedure...", this is fine IMO since this makes it a unit-local variable and not a global).

HTH,
M.


Sweet! Works like a charm. I even cranked it up to 20fps and it ran no problem for an hour .

Thank you very much.

I was thinking I was going to have to make a global variable and convert the function to a procedure, this is much better. Always good to learn some technique!

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages - MoreDelphi Programming > Result:TBitmap Memory Leak???


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump


Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 





© 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
Stay green...Green IT