[delphi] - assign een bitmap met waarde nil

Pagina: 1
Acties:

  • MisterE
  • Registratie: April 2002
  • Laatst online: 28-08 19:15
Weet iemand een simpele manier om dit te laten werken.

procedure TForm1.Button1Click(Sender: TObject);
var
bm : TBitmap;
begin
bm := TBitmap.Create;
bm := nil;
bm.LoadFromFile('c:\MisterE.bmp');
image1.Picture.Bitmap := bm;
bm.Free;
end;

Het probleem is dat bm eerst 'Nil' toegewezen krijgt.
Is er een manier om dit te 'undo'.
bm is op dat moment nog niet 'Free' daarom snap ik
niet waarom ik niet weer een nieuw bitmap mag creeren.

btw: ik begrijp dat de code werkt door 'nil' weg te halen maar in
mijn applicatie kan deze situatie voorkomen

Verwijderd

Na 'bm := TBitmap.Create' wijst bm naar een geheugenlocatie waar een TBitmap instantie staat. Na 'bm := nil' wijst bm naar geheugenlocatie 0. Als je verder geen verwijzing hebt naar de TBitmap instantie, dan ben je hem kwijt; lijkt me logisch; Pointers hebben geen geheugen ofzo.

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Wat jij hier post is absolute nonsens in Delphi-termen. Je creëert een TBitmap object en wijst dan nil toe aan de pointer naar je object. Ergo, een memleak en een onbruikbare referentie, dat is niet wat je wil.

Je moet even uitleggen waarom dit in jouw situatie voor kan komen, en hoe dan precies. Ik vermoed dat je bedoelt dat de bitmap in TBitmap leeg moet zijn, maar ik weet het niet zeker (overigens doe je dat dan met
code:
1
bm.Assign(nil)
)

Verwijderd

code:
1
bm.Assign(nil);

Zal echt niet gaan werken aangezien je een afgeleide van TPersistent op geen enkele wijze naar een void-pointer (nil) kan toewijzen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.Voorbeeld;
var
  bm: TBitmap;
begin
  bm:=TBitmap.Create;
  try
    bm.Width := 100;
    bm.Height := 100;
    bm.Canvas.MoveTo(0, 0);
    bm.Canvas.LineTo(100, 100);
    DeleteObject(bm.ReleaseHandle);
    Canvas.Draw(0, 0, bm);
  finally
    bm.Free;
  end;
end;

Does the trick...

En dan nu nog een klein lesje m.b.t. tot pointers
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type
  TTestObj=class
  private
    FMemory: Pointer;
    FNumberOfBytes: Integer;
  public
    constructor Create(ANumberOfBytes: Integer);
    destructor Destroy; override;
  end;

constructor TTestObj.Create(ANumberOfBytes: Integer);
begin
  inherited Create;
  FNumberOfBytes:=ANumberOfBytes;
  GetMem(FMemory, FNumberOfBytes);
end;

destructor TTestObj.Destroy;
begin
  FreeMem(FMemory, FNumberOfBytes);
  inherited Destroy;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TObj: TTestObj;
begin
  TObj:=TTestObj.Create(16777216); // Kunnen we mooi zien in Windows taakbeheer
  TObj:=nil;
end;

Hierbij heb je een memoryleak van ~16 Megabytes. Nou wordt die 16 megabytes wel opgeruimd zodra je applicatie wordt opgeruimd maar echt netjes is het niet.

Hoe dit mogelijk is?

Niet alleen je zelf gedefinieerde variabelen hebben een reference naar de gecreëerde objecten; ook wordt er een reference 'onderwater' bijgehouden zodat bij het sluiten van je applicatie ook deze kunnen worden vrijgegeven. Met O:=TObject.Create; en O:=nil; wordt O dus niet vrijgegeven aangezien na O:=TObject.Create; de reference count op 2 staat i.p.v. 1. Na O:=nil; is de reference count nog steeds 1 en pas bij een reference count van 0 wordt het O gedestroyed.

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Verwijderd schreef op 31 juli 2002 @ 09:38:
code:
1
bm.Assign(nil);

Zal echt niet gaan werken aangezien je een afgeleide van TPersistent op geen enkele wijze naar een void-pointer (nil) kan toewijzen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.Voorbeeld;
var
  bm: TBitmap;
begin
  bm:=TBitmap.Create;
  try
    bm.Width := 100;
    bm.Height := 100;
    bm.Canvas.MoveTo(0, 0);
    bm.Canvas.LineTo(100, 100);
    DeleteObject(bm.ReleaseHandle);
    Canvas.Draw(0, 0, bm);
  finally
    bm.Free;
  end;
end;

Does the trick...
Mag je mij vertellen waarom het volgende wel werkt, in tegenstelling tot wat je beweert. Misschien zie ik iets gigantisch over het hoofd, maar ik heb altijd met bitmap.Assign(nil) gewerkt en nooit problemen mee gehad.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TForm1.Button1Click(Sender: TObject);
var
  bm: TBitmap;
begin
  bm := TBitmap.Create;
  try
    bm.LoadFromFile('c:\mijn documenten\mijn afbeeldingen\fia.bmp');
    Image1.Picture.Assign(bm); //staat ie op mn form
    ShowMessage('ready to assign NIL to bm');
    bm.Assign(nil);
    Image1.Picture.Assign(bm); //en nou is ie weer weg
  finally
    bm.Free;
  end;
end;

  • MisterE
  • Registratie: April 2002
  • Laatst online: 28-08 19:15
maar ik zal mijn probleem ff verder uitlegggen:
ik neem een file (bitmap,jpeg etc) die zet ik met een procedure om.
Ik gebruik daarvoor een variabele (van het var type), die procedure kan natuurlijk verkeerd gaan. Dus dacht ik wijs ik bij 'except' gewoon nil aan die bitmap toe.

Maar als dit dus niet goed ik dan wil dit graag weten.
Maar ik zie hier ook een beetje tegenstrijdige berichten.

ik gebruik dus:


Procedure ConvertGraphic2BMP(var Dest : TBitmap; const FilePath: string);
var
Picture: TPicture;
begin
Picture := TPicture.Create;

Try
Picture.LoadFromFile(FilePath);

Try
Dest.Assign(Picture.Graphic);
Except
Dest := NiL;
End;

Except
Dest := NiL;
End;

Picture.Free;
end;

Dit werkt prima, alleen files van '0 bytes' komen erdoorheen :(
En daarna kunnen soms nog 2 of 3 procedures komen die moeten stretchen, tile etc.
Daarom zet ik eerst het file om naar bitmap, anders moet je allemaal verschillende routines maken (en een windoze wallpaper moet toch BMP zijn)

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

Het is niet zo'n goed idee om Dest := nil te doen als er iets mis gaat. De aanroepende procedure heeft de pointer (TBitmap) gecreëerd (geheugen gereserveerd), die moet dus in principe ook de mogelijkheid hebben om de TBitmap weer te Free-en. Als er iets mis gaat in je ConvertGraphic2BMP, dan vervalt die mogelijkheid omdat de aanroepende procedure met een Nil pointer opgescheept zit.

En wat bedoel je met 'alleen files van 0 bytes komen erdoorheen'? Dat TPicture.LoadFromFile niet klaagt als je een invalid format laadt of zo?

Verwijderd

Verwijderd schreef op 31 juli 2002 @ 09:38:
Niet alleen je zelf gedefinieerde variabelen hebben een reference naar de gecreëerde objecten; ook wordt er een reference 'onderwater' bijgehouden zodat bij het sluiten van je applicatie ook deze kunnen worden vrijgegeven. Met O:=TObject.Create; en O:=nil; wordt O dus niet vrijgegeven aangezien na O:=TObject.Create; de reference count op 2 staat i.p.v. 1. Na O:=nil; is de reference count nog steeds 1 en pas bij een reference count van 0 wordt het O gedestroyed.
Objecten met reference counting :? Kun je me ff een link naar zo'n verhaal geven, want hier heb ik nog nooit van gehoord.

Ik ken alleen reference counting bij strings, interfaces en dynamische arrays..

  • Delphi32
  • Registratie: Juli 2001
  • Laatst online: 31-08 21:58

Delphi32

Heading for the gates of Eden

LOL als er reference counting was in Delphi, waarom dan geen garbage collector? Maw DiFool, je slaat de spijker op den kop ( 8)7 )
Pagina: 1