Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 4/5 - 2 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Free vs FreeAndNil
#11
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol

freeandnil kullanimi tavsiye edilmiyor. metodun icerisinde bile SimaWB ' nin dedigi gibi siralama hatasi var Smile
WWW
Cevapla
#12
Merhaba,

Ben burada Nick Hodges gibi düşünüyorum, ama çok da katı değilim. Sürekli FreeAndNil kullanmak bence iyi bir iki değil. Bunun bir iki sebebi var:

1. Eğer sürekli FreeAndNil'e ihtiyaç duyuyorsanız ve bunun hata sayısını azalttığını düşünüyorsanız aynı zamanda "Hiding Errors / Handling Errors' ikilisinden "Hiding Errors"ü seçmiş oluyorsunuz. Delphi'de nil olan bir nesneyi Free edebilirsiniz ve bu bir hata değildir. try/finally örgülerinden birisi de Delphi'nin bu özelliğini kullanmaktır. Örneğin aşağıdaki kod buna güzel bir örnek:

var
 A, B: TMyObject;
begin
 A := nil;
 B := nil;
 try
   A := TMyObject.Create;
   B := TMyObject.Create;
   ...
 finally
   A.Free;
   B.Free;
 end;
end;

A := TMyObject.Create satırında hata çıksa bile finally kısmında B.Free satırında hata oluşmayacaktır. Bahsettiğim durum buydu. Şimdi bu niye Hiding Errors olsun? Çok basit, sizin kodunuz ve senaryonuz, o nesnenin Free edilmemiş olmasını istiyor, ama bir şekilde Free edilmiş. Yani kod aslında sizin istediğiniz gibi çalışmamış. Siz de "madem bu tür sorunlar oluyor, o zaman ben nesneleri nil yapayım da bana dereference edilmiş nesneleri free etmeye çalıştığımda hata vermesin" demiş oluyorsunuz.

2. FreeAndNil sizin adınıza bir assignment yapıyor. Özellikle Local nesneleri free ederken ne gerek var işimize yaramayacak bir assignment yapmaya? Global nesnelerde durum biraz daha karışık. "Global variables are evil" diye bir deyiş var, Türkçe'si "Global değişkenler kötüdür". Ben de böyle düşünüyorum. O yüzden mümkün olduğu kadar da kullanmamaya çalışıyorum. Kullandıklarımda da FreeAndNil'e ihtiyaç duymayacak bir tasarım yapmaya çalışıyorum. Diğer bir deyişle, programın akışını kontrol altında tutuyorum. Eğer bir sorun çıkar da hata alırsam, bunu saklamaya değil, çözmeye çalışıyorum. Bir nesneyi free etmeme rağmen benim kodum nasıl olur da ona tekrar erişmeye çalışır? Bu hatayı tespit etmek çok daha mantıklı.

Bütün bunlar dışında FreeAndNil'i hiç mi kullanmıyorum? Kullanıyorum ama çok az. Her kullandığımda da iki kere düşünüyorum, ben niye bunu kullanmak zorunda kaldım diye. 

İyi çalışmalar
Cevapla
#13
Öncelikle belirtmek isterim ki; Delphi'de Free edilmiş ve nil'e eşitlenmiş (Pointer(0)) bir nesne işaretçisi üzerinden tekrar Free çağrımı yapabilirsiniz ve bu bir hataya neden olmaz. Ama neden ? Çünkü TObject.Free metodunda;

  if Self <> nil then

    Destroy;

gibi bir kod vardır. FreeAndNil var iken bu nimetten istifade etmemek bence çok yersiz ve gereksizdir. Basitçe aşağıdaki kodları çalıştırın:

procedure TForm1.Button1Click(Sender: TObject);
var
 C : TComponent;
begin
 c := TComponent.Create(nil);
 ShowMessage('1-' + C.ToString);
 C.Free;
 ShowMessage('2-' + C.ToString);
end;

Ekranda, nesne yok edildikten sonra bile bir şeyler görüyorsunuz değil mi ? (Bu örnek için TComponent).

Peki bir de şu örneği çalıştırın:

procedure TForm1.Button1Click(Sender: TObject);
var
 C : TComponent;
begin
 c := TComponent.Create(nil);
 ShowMessage('1-' + C.ToString);
 FreeAndNil( C );
 ShowMessage('2-' + C.ToString);
end;

Peki şimdi ne görüyorsunuz ? Bekleneni, yani bir Access Violation hatasını görüyor olmalısınız. 

Free çağrımının tehlikesini fark edebildiniz mi ? Eğer edemedi iseniz, küçücük bir soru ile aklınızı meşgul etmeye çalışayım:

C isimli TComponent türündeki nesne Free edildiğinde; C için hafızada tahsis edilen alan işletim sistemine iade edilir; ancak C hâla hafızanın ilgili bölgesini işaret etmektedir. C nesnesi Free edildikten sonra; Memory Manager yeni bir TComponent türündeki D değişkeni için hafızada bir tahsisat yapsa ve tamamen tesadüfen C'nin gösterdiği lokasyonu ayırsa ne olur ?

Bu durumda; C ve D aynı hafıza bölgesini göstermektedirler. Ancak o bölge gerçekte artık tamamen farklı bir nesneye ait(D), oysa C'de aynı bölgeyi gösteriyor ve her ikiside (C ve D) bir TComponent türevi ise; bu durumda C üzerinden yapılan bir çağrı D'nin virtual metodlarının çağrılmasına neden olur.

 Biliyorum biraz karmaşık yazmış olabilirim. Ancak bunu kağıt üstüne çizerek düşünür iseniz; ne demek istediğimi çok daha iyi anlayacaksınız.

Ayrıca FreeAndNil içindeki çağrımın sırasında bir hata yoktur. Bilerek ve isteyerek o şekilde dizayn edilmiştir. Bir nesnenin Destroy metodu içinden nesne instance pointer'ının kullanımı hatalıdır(değişken) ve bu hata tespit edilebilsin diye öncelikle instance pointer'ı nil'e set edilir, ardından Destroy'a dallanılır.

Free kullanmak gereksiz yere riske girmektir ve bunun mantıklı bir nedeni yoktur. C/C++ gibi dillerde uygulama geliştiren insanların null (nil) pointer'larla başlarının ne kadar derde girdiğini bilmeyenlerin bu hususta aynı hassasiyeti göstermeleri elbette çok fazla beklenemez.

 Pointer'lar ile çalışmak dikkat gerektirir ve FreeAndNil, Assigned metodları bu hususta son derece faydalı metodlardır.

Free kullanıyorsanız ve instance pointer'ını nil'e eşitlemediyseniz; başınıza bir sürü sıkıntı gelebilir. Bunlardan en kompleksini yukarıda bir soru ile dikkatinize sundum. Bir başkası ve sıklıkla karşılaşılan ise multi free olayıdır. Free edilen bir nesne hafızadan zaten temizlenmiş ve ayrılan hafıza işletim sistemine yeniden iade edilmiştir. Ancak; ilgili değişken nil olmadığı için siz bu hafızanın iade edilip edilmediğini bilemezsiniz. Bu durumda; yeniden bir Free çağrımı yapma ihtimaliniz söz konusudur.

 Böyle bir durumda neler olabilir ?

1- Daha önce tahsis edilmiş ve daha sonra işletim sistemine iade edilmiş hafıza bloğuna başka bir tahsisat yapılmamıştır ve yeni bir boşaltma talebi hatayla neticelenir.

2- Daha kötüsü; ilgili hafıza lokasyonuna başka bir nesne (X değişkeni diyelim) yerleşmiş olabilir. Sizin Free çağrınız o nesnenin kullandığı hafızayı işletim sistemine iade edebilir. Ardından X değişkenine erişmeye çalışırsınız ve anlamlandıramadığınız hatalar alırsınız.

....

Daha fazla bu husus hakkında konuşmayı gerekli görmüyorum. Free yerine FreeAndNil yazarak, bir çok sıkıntıyı daha başlamadan bertaraf edebilmek var iken; neden kapıyı pencereyi açık bırakıp, hırsızlara davetiye çıkartalım ki ?
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#14
Ayrıca ek olarak belirtmek isterim ki; FreeAndNil kullanmış olmanıza rağmen; her zaman ama her zaman Assigned ile kontol yapın. Neden ?

Aşağıdaki örneği çalıştırın:

  TTest = class
  public
   procedure Deneme;
 end;

{ TTest }

procedure TTest.Deneme;
begin
  ShowMessage('Merhaba bu bir deneme mesajıdır');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  T : TTest;
begin
  T := TTest.Create;
  T.Deneme;
  FreeAndNil(T);
  T.Deneme;
end;

Ekranda ne görüyorsunuz ? İki aynı ShowMessage değil mi ! Şaşırdınız mı ?

Şaşırmanıza gerek yok. Nesne instance'ı nil dahi olsa ilgili metod çağrımı gerçekleştirilir ve ilgili metod içinde o nesnenin hafıza alanına müracaat eden hiç bir şey yok ise; bu durumda ilgili metod %100 işletilir. Örneğimizde olduğu gibi. Ancak örneği azıcık değiştirip yeniden deneme yaapalım. Buyrun:



  TTest = class
  public
   procedure Deneme;
 end;

{ TTest }

procedure TTest.Deneme;
begin
  ShowMessage('Merhaba bu bir deneme mesajıdır.Şimdi ilgili nesneye ait hazıfa bloğundan bir şeyler kullanacağız:' + Self.ClassName);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  T : TTest;
begin
  T := TTest.Create;
  T.Deneme;
  FreeAndNil(T);
  T.Deneme;
end;

Peki şimdi ne görüyorsunuz ?

Umarım gördükleriniz, FreeAndNil ve Assigned kullanımlarının ehemmiyetini size anlatmama vesile olmuştur.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#15
Ellerinize saglik.
Cevapla
#16
(01-02-2018, Saat: 13:01)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlAyrıca ek olarak belirtmek isterim ki; FreeAndNil kullanmış olmanıza rağmen; her zaman ama her zaman Assigned ile kontol yapın. Neden ?

Aşağıdaki örneği çalıştırın:

  TTest = class
  public
   procedure Deneme;
 end;

{ TTest }

procedure TTest.Deneme;
begin
  ShowMessage('Merhaba bu bir deneme mesajıdır');
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  T : TTest;
begin
  T := TTest.Create;
  T.Deneme;
  FreeAndNil(T);
  T.Deneme;
end;

Ekranda ne görüyorsunuz ? İki aynı ShowMessage değil mi ! Şaşırdınız mı ?

Şaşırmanıza gerek yok. Nesne instance'ı nil dahi olsa ilgili metod çağrımı gerçekleştirilir ve ilgili metod içinde o nesnenin hafıza alanına müracaat eden hiç bir şey yok ise; bu durumda ilgili metod %100 işletilir. Örneğimizde olduğu gibi. Ancak örneği azıcık değiştirip yeniden deneme yaapalım. Buyrun:



  TTest = class
  public
   procedure Deneme;
 end;

{ TTest }

procedure TTest.Deneme;
begin
  ShowMessage('Merhaba bu bir deneme mesajıdır.Şimdi ilgili nesneye ait hazıfa bloğundan bir şeyler kullanacağız:' + Self.ClassName);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  T : TTest;
begin
  T := TTest.Create;
  T.Deneme;
  FreeAndNil(T);
  T.Deneme;
end;

Peki şimdi ne görüyorsunuz ?

Umarım gördükleriniz, FreeAndNil ve Assigned kullanımlarının ehemmiyetini size anlatmama vesile olmuştur.

Bir de şöyle bir açılım yapılım o zaman  Big Grin

TTest = class
 private
  FInitValue: string;
 public
  constructor Create(AInitValue: string); overload;
  procedure Deneme;
end;


constructor TTest.Create(AInitValue: string);
begin
   fInitValue := AInitValue;
end;

procedure TTest.Deneme;
begin
  ShowMessage('Merhaba bu bir deneme mesajıdır.Şimdi ilgili nesneye ait hazıfa bloğundan bir şeyler kullanacağız:' + Self.ClassName + ' "' + fInitValue + '"');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  T : TTest;
begin
  T := TTest.Create('DelphiCan');
  T.Deneme;
  T.Free;
  T.Deneme;
end;
Cevapla
#17
Alıntı:Şaşırmanıza gerek yok. Nesne instance'ı nil dahi olsa ilgili metod çağrımı gerçekleştirilir ve ilgili metod içinde o nesnenin hafıza alanına müracaat eden hiç bir şey yok ise; bu durumda ilgili metod %100 işletilir.

Zaten ifade etmek istediğinizi ifade etmeye çalışmıştım daha önce Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#18
FreeAndNil konusunda ben de nick gibi dusunuyorum. Zorunlu olmadikca FreeAndNil kullanmamak gerekir. Kodun hatasiz calismasini saglamak icin FreeAndNil'e guvenmek tasarimda bir yerde sorun oldugunun isaretcisi olabilir. Ornek vermek gerekirse;


procedure TForm1.Button1Click(Sender: TObject);
var
C : TComponent;
begin
c := TComponent.Create(nil);

FreeAndNil( C );
FreeAndNil( C );

end;

Basit bir kod yazdim ama siz bu durumu daha karmasik bir uygulama icin dusunebilirsiniz. Ayni nesne iki kere free ediliyor ve ortaya hic bir hata cikmiyor. Burda bir sorun yok mu ? 
Tasariminizi gozden gecirmelisiniz. Cunku ayni nesne iki kere yokediliyor ve FreeAndNil kullandiginiz icin herhangi bir uyari almiyorsunuz ve herseyin duzgun oldugunu saniyorsunuz.



Simdi diger koda bakalim.


procedure TForm1.Button1Click(Sender: TObject);
var
C : TComponent;
begin
c := TComponent.Create(nil);

C.Free;
C.Free;

end;

Bu kodu calistirdiginizda Delphi size "invalid pointer operation" hatasi verecektir ve sizde "Zaten free ettiğim bir nesneyi neden baska bir yerde daha free ediyorum acaba?" sorusunun pesine duserek tasariminizdaki hatayi bulup yok edeceksiniz.

Velhasili kelam nesneleri olusturup yok ederken iki kere dusunmek lazim Smile
WWW
Cevapla
#19
(01-02-2018, Saat: 20:41)sadettinpolat Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlFreeAndNil konusunda ben de nick gibi dusunuyorum. Zorunlu olmadikca FreeAndNil kullanmamak gerekir. Kodun hatasiz calismasini saglamak icin FreeAndNil'e guvenmek tasarimda bir yerde sorun oldugunun isaretcisi olabilir. Ornek vermek gerekirse;


procedure TForm1.Button1Click(Sender: TObject);
var
C : TComponent;
begin
c := TComponent.Create(nil);

FreeAndNil( C );
FreeAndNil( C );

end;

Basit bir kod yazdim ama siz bu durumu daha karmasik bir uygulama icin dusunebilirsiniz. Ayni nesne iki kere free ediliyor ve ortaya hic bir hata cikmiyor. Burda bir sorun yok mu ? 
Tasariminizi gozden gecirmelisiniz. Cunku ayni nesne iki kere yokediliyor ve FreeAndNil kullandiginiz icin herhangi bir uyari almiyorsunuz ve herseyin duzgun oldugunu saniyorsunuz.



Simdi diger koda bakalim.


procedure TForm1.Button1Click(Sender: TObject);
var
C : TComponent;
begin
c := TComponent.Create(nil);

C.Free;
C.Free;

end;

Bu kodu calistirdiginizda Delphi size "invalid pointer operation" hatasi verecektir ve sizde "Zaten free ettiğim bir nesneyi neden baska bir yerde daha free ediyorum acaba?" sorusunun pesine duserek tasariminizdaki hatayi bulup yok edeceksiniz.

Velhasili kelam nesneleri olusturup yok ederken iki kere dusunmek lazim Smile

Sadettin'im, sanırım şu an laz inadı yapıyorsun Smile

FreeAndNil kodun hatasız çalışması için bir güven unsuru değil. Kodu en tehlikeli unsurdan (insan) korumak için gereken zaruri bir etkendir. Bir kod önce programcısından korunmalıdır. Çünkü kod için en tehlikeli kişi programcıdır. Bu nedenle; her daim kontrollü olmak zarar getirmez, fayda verir.

Neye itiraz ettiğinizi anlayamıyorum cidden. FreeAndNil nesneyi Free ettikten sonra ilgili poıinter'ı da Nil'e eşitler. Bu kadar üşengeç misiniz ? Yukarıda, Free'nin çıkartabileceği arızaları saydım, FreeAndNil'in faydalarını saydım. Hâla neden ısrarla hatalara neden olabilecek bir hususu takip etme gereği hissediyorsunuz ?

Burada sorun tasarım problemi değildir. Sorun insan faktörüdür. İnsanlar hata yapar. Bu hataları minimize etmeye çalışmak ve kontrollü kod yazmaya çalışmanın sizlere bir zararı olmaz faydası olur emin olun.

Alıntı:Basit bir kod yazdim ama siz bu durumu daha karmasik bir uygulama icin dusunebilirsiniz. Ayni nesne iki kere free ediliyor ve ortaya hic bir hata cikmiyor. Burda bir sorun yok mu ?

Evet burada bir sorun yok. Neden yok ? Daha önce de yazmıştım. TObject.Free metodunun içine bakarak da görebilirsiniz. Delphi'yi geliştiren insanlar, ellerinden gelen önlemleri almaya çalışmışlar. Ne yapmışlar peki , Self Nil'den farklı mı diye kontrol etmişler.

Sorun olarak, iki tane FreeAndNil'in ard arda konulmasından bahsediyorsan eğer; zaten normal bir programcı bunu yapmaz. Bunu Copy/Paste'ci programcı belki yapar. Multi Free hataları tamamen başka nedenler ile çıkar, bu kadar basit söz dizim yanlışları nedeni ile değil.

Yazdığım iki mesajı da dikkat ile okuyup deneyen arkadaşlarımın Free kullanmanın sıkıntılarını gözlemleyeceğini umut ediyordum ama insanlar senin Free kullanımını teşvik ettiğin mesaja puan verdiklerine göre, sanırım yeterince iyi aydınlatamadım demek ki.

TObject.Free kullanmak demek, hafızayı iade etmek demek ancak ilgili hafıza bölgesine geçersiz bir işaretçi bırakmak demektir. Ve bu işaretçi üzerinden kontrol yapılması gerektiğinde hafızanın iade edilip edilmediğini anlayamamak demektir.(Aslında iade edilmediğini görmek demektir) Dolayısı ile iade edilmiş bir hafızayı yeniden iade etmeye çalışabilme ihtimali demektir, iade edilmiş bir hazıfa bölgesine erişmeye çalışıp AV hataları almak demektir, tamamen tesadüf eseri aynı hafıza bölgesine bir başka nesnenin yerleşmesi üzerine bir başka nesnenin metodlarını yanlışla çağırmak demektir, ya da bir başka nesnesi istemeden Free etmek demektir.

Daha ne söyleyeyim sizlere bilmiyorum ki ?


Bir de sizler FreeAndNil'in oluşturabileceği ciddi sıkıntılardan bahsedin de, ben de sizlerin gördüğü ama benim bir türlü göremediğim sorunları göreyim !

Not: Bu arada Nick dediğiniz adama çok da bel bağlamayın. Çok abartmayın kendisini. Bildiğim şeyler var ama açıktan yazmak bana yakışmaz.
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#20
Benim anladığım ;
Free ile hafızadan serbest bırakmak yetmez, ilgili hafıza bloğuda Nil ile temizlenmelidir ki ayrılmış olan alan tamamen boş görünsün, zira ileride buraya yerleşebilecek olası farklı nesnelerin metodlarına yanlışlıkla create ettiğimiz nesne adıyla ulaşamayalım.
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
WWW
Cevapla

Konuyu Paylaş : facebook gplus twitter



Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Nesne Create ve free ile ilgili sorum var. yhackup 10 1.215 03-03-2017, Saat: 11:18
Son Yorum: Tuğrul HELVACI
  Datasetin bağlı olduğu Myquery'i free Etmek (MemoryLeak Tespiti) yhackup 18 8.765 29-11-2016, Saat: 15:38
Son Yorum: yhackup
  Create Edilen Clasları bulup kontrollu free etmek yhackup 2 1.491 18-09-2016, Saat: 11:57
Son Yorum: yhackup



Konuyu Okuyanlar: 2 Ziyaretçi