Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 2019
-
27 janv. 2007 à 17:16
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 2019
-
28 janv. 2007 à 15:53
Salut à tous,
Une question existentielle me tourmente...
Je vous donne un petit exemple, ce sera plus simple:
function Bidouiller(BtmSource : TBitmap) : TBitmap;
begin
result := TBitmap.create;
... // ici, on bidouille le
... // BtmSource et on l'affecte
... // à result.
end;
Ca fonctionne très bien, mais la question qui me turlupine c'est que le TBitmap créé pour result n'est de fait jamais libéré.
Comment doit-on gérer cela?
Je vais essayé d'etre un ptit moins expéditif que Julio .
Je me suis posé la même question il y a pas longtemps et j'ai opté pour la solution de Julio. Mais ca m'a turlupiné. Mais d'un autre coté result := TBitmap.create; me gène aussi beaucoup sur le principe peut etre encore plus que la question . En effet je ne concois pas (conceptuellement je parle) de créer le résultat d'une fonction. Du reste ce qui est valable pour un TBitMap l'est pour tout : TStringList, TMemo ect ect
JulioDelphi
Messages postés2226Date d'inscriptiondimanche 5 octobre 2003StatutMembreDernière intervention18 novembre 201014 27 janv. 2007 à 19:08
BINGO ^^
Le fBmpTemp doit etre libéré apres, une histoire de pointeur je pense.
************************************
var
Form1: TForm1;
fBmpTemp: TBitmap;
implementation
{$R *.dfm}
function Bidouiller1(BtmSource:TBitmap):TBitmap;
begin
result := TBitmap.create;
result.Height := BtmSource.Height div 2;
result.Width := BtmSource.Width div 2;
result.Canvas.Draw(0,0,BtmSource);
end;
function Bidouiller2(BtmSource:TBitmap):TBitmap;
begin
fBmpTemp := TBitmap.create;
fBmpTemp.Height := 1;
fBmpTemp.Width := 1;
fBmpTemp.Height := BtmSource.Height div 2;
fBmpTemp.Width := BtmSource.Width div 2;
fBmpTemp.Canvas.Draw(0,0,BtmSource);
result := fBmpTemp;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Image2.Picture.Assign(Bidouiller1(Image1.Picture.Bitmap));
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Image2.Picture.Assign(Bidouiller2(Image1.Picture.Bitmap));
fBmpTemp.free;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Image2.Picture.Assign(nil);// PAS OK!
end;
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 27 janv. 2007 à 20:04
Salut,
alors oui ... sauf cas spéciaux
function Bidouiller1(BtmSource:TBitmap):TBitmap;
begin result := TBitmap.create;
result.Height := BtmSource.Height div 2;
result.Width := BtmSource.Width div 2;
result.Canvas.Draw(0,0,BtmSource);
end ;
Utilisation :
Var BMP : TBitmap;
Begin Try BMP : = Bidouiller1(Image1.Picture.Bitmap);
.......
Finally BMP.Free; // le Bitmap crée par la fonction Bidouiller1 est libéré ici End;
End;
procedure TForm1.BtnDirectBidouilleClick(Sender: TObject);
begin
Bidouiller(Image1.Picture.Bitmap, Image2.Picture.Bitmap);
end;
procedure TForm1.BtnBufferedBidouilleClick(Sender: TObject);
var Buffer : TBitmap;
begin
Buffer := TBitmap.Create;
try
Bidouiller(Image1.Picture.Bitmap, Buffer);
Image2.Picture.Bitmap.Assign(Buffer);
finally
Buffer.Free;
end;
end;
end.
et en plus c'est plus rapide a s'executer en procedure et ça regle tout probleme de liberation car ca ne doit jamais etre la fonction ou procedure qui est en charge de la creation d'une instance d'objet!
Vous n’avez pas trouvé la réponse que vous recherchez ?
JulioDelphi
Messages postés2226Date d'inscriptiondimanche 5 octobre 2003StatutMembreDernière intervention18 novembre 201014 27 janv. 2007 à 17:42
function Bidouiller(BtmSource : TBitmap) : TBitmap;
var
fBmpTemp: TBitmap;
begin
fBmpTemp := TBitmap.create;
... // ici, on bidouille le
... // BtmSource et on l'affecte
... // à result.
result := fBmpTemp;
fBmpTemp.free;
end;
Caribensila
Messages postés2527Date d'inscriptionjeudi 15 janvier 2004StatutMembreDernière intervention16 octobre 201918 27 janv. 2007 à 18:31
J'suis con ou quoi, moi?
Voici mon petit programme de test bidon:
implementation{$R *.dfm}
function Bidouiller1(BtmSource:TBitmap):TBitmap;//CA MARCHE
begin
result := TBitmap.create;
result.Height := BtmSource.Height div 2;
result.Width := BtmSource.Width div 2;
result.Canvas.Draw(0,0,BtmSource);
end;
function Bidouiller2(BtmSource:TBitmap):TBitmap;//CA MARCHE PAS
var fBmpTemp: TBitmap;
begin
fBmpTemp := TBitmap.create;
try
fBmpTemp.Height := BtmSource.Height div 2;
fBmpTemp.Width := BtmSource.Width div 2;
fBmpTemp.Canvas.Draw(0,0,BtmSource);
result.Height := fBmpTemp.Height;
result.Width := fBmpTemp.Width;
//result := fBmpTemp; // -> ERREUR! EAccessViolation
//result.Assign(fBmpTemp); //-> ERREUR! EAccessViolation
result.Canvas.Draw(0,0,fBmpTemp);//-> ERREUR! EAccessViolation
finally fBmpTemp.free; end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Image2.Picture.Assign(Bidouiller1(Image1.Picture.Bitmap));// OK!
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Image2.Picture.Assign(Bidouiller2(Image1.Picture.Bitmap));// PAS OK!
end;
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 27 janv. 2007 à 19:47
Salut à tous,
Aïe aïe aïe ! Lorsque vous créez un objet, il faut absolument penser à le détruire ! Dans le code de Julio (le dernier), rien ne libère rien ! Le fait que l'objet soit crée par une fonciton ne change rien à la règle !
Il faut TOUJOURS affecter le résultat de la fonction dans une variable locale que l'on détruit après. Sinon, fuite de mémoire assurée.
[ Sauf, cas spéciaux, bien sûr, mais je n'en parlerais pas ici, n'est-ce pas Cirec ? ^^ ]
Bon, à bientôt pour un tutorial car ce genre de question à l'air d'en turbinlicoter plus d'un ...
JulioDelphi
Messages postés2226Date d'inscriptiondimanche 5 octobre 2003StatutMembreDernière intervention18 novembre 201014 27 janv. 2007 à 20:21
Ah ok ! Mais donc on ne peut pas utiliser :
Image1.Picture.Bitmap.Assign(Bidouiller1(Image1.Picture.Bitmap));
?
Et si on est obligé de l'utiliser comme ça (pour une raison X ou Y), ma soluce reste t-elle bonne ou effectivement je ne libere rien.
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 28 janv. 2007 à 14:51
alors la tu es en train de dire que Borland à fait n'importe quoi ... et qu'ils sont donc tous, par la même, sous l'effet de drogues
ça c'est n'importe quoi
le tout est de savoir comment faire pour liberer l'objet que la fonction vient de créer
étant donné les contrôles que tu es obligé de faire dans ta procédure je doute que ce soit plus rapide qu'une fonction
et même si c'était le cas ça se compte en nano-secondes ... pfff ... donc imperceptible pour nous
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 28 janv. 2007 à 15:20
@f0xi: comme tu le dis si bien, faut arreter la drogue ... :-)
Une fonction, au niveau du code généré (assembleur), n'est ni plus ni moins d'une procédure.
Si tu veux t'en persuader, reparde le code ASM crée par Delphi sur ces deux appels :
C'est strictement la même chose. Une fonction retourne son résultat dans EAX.
Or, en convention Register, le premier paramètre d'une procedure est aussi EAX (sauf fonction d'objet), le deuxième EBX, puis ECX, et enfin les autres sont empilés, ce qui signifie que ces deux appels sont les mêmes... CQFD !
Allez, on te pardonne, c'est la neige qui réverbère dans tes neurones ... lol ^^