Çıkmaza sokan bir hata !

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

Merhaba arkadaşlar hepinize şimdiden teşekkür ederim.

Benim bir hata ile başım dertte, bu hata bir işlemi yaparken karşıma çıkıyor.

HATA : access violation at the adress 0000000 read of adress 0000000

Yaptığım işlem : MDIForm üzerinde toolbar yardımı ile yeni bir ChildMDIForm Creat ediyorum. (View Sourcedeki Project1.dpr dosyası içinde creat etmiyorum toolbardaki button ile yeniden creat ediyorum.)

Bildiğiniz üzere child forumları kapatma işlemi simge durumuna küçültmek ile ibaret. Ben OnClose eventine Action := caFree; koyarak kapatma işlemini gerçekleştirdim. Bir kaç form oluşturuyorum. Hepsini ilk etapta kapatıyorum problem yok. Ama ikinci kez hepsini açarken yani tekrar creat olayı gerçekleşirken bu hatayı alıyorum.. Muhakkak birinde veriyor sonraki hepsini kapatıp açmada bu ikiye çıkıyor her defasında artıyor.

Action := caFree; yerinede Destroyer; kullandım aynı işlemi görüyor ama aynı hataya buda neden oluyor..

Problemi bir türlü çözemedim..
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
qamyoncu
Üye
Mesajlar: 266
Kayıt: 12 Tem 2008 04:30

Re: Çıkmaza sokan bir hata !

Mesaj gönderen qamyoncu »

Kod: Tümünü seç

procedure FormClose(Sender: TObject; var Action: TCloseAction);
begin
(Sender as TForm).Free;
end;
ChildForm'ların OnClose yordamlarını bu yordama eşitlemen yeterli olmalı :)


Konunun ismini de daha anlaşılır yaparsanız sevinirim. :)
Batuhan TAŞDÖVEN
'Yükseldikçe küçülen bir uçurtma..'
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

Beni çıkmaza soktuğu için öyle yazdım uzun yazmaktanda kısaca başlıkta bir hata olduğunu belirtmek istedim.

Verdiğiniz kodu deniyorum. Teşekkürler.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

Aynı problem devam ediyor. Ama bu sefer bazen komple programı kapatıyor :s

Komple kapatma olayını create yaparken yapıyor.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
qamyoncu
Üye
Mesajlar: 266
Kayıt: 12 Tem 2008 04:30

Re: Çıkmaza sokan bir hata !

Mesaj gönderen qamyoncu »

Şuan bir programda aynı kodu kullanıyorum ve hiç sorun çıkmıyor.

Kodlarını yazarsan yardım edebilirim
Batuhan TAŞDÖVEN
'Yükseldikçe küçülen bir uçurtma..'
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

Toolbar buttonlarına tıklayınca uygulanan create yordamı !

Kod: Tümünü seç

 if ChildMDIForm1.Caption <> '' Then // Açılmaya çalışan fom'un başlığı eşit değilse Null'e bu forum açık demektir ve Show işlemini yapıyor.
  Begin
   ChildMDIForm1.Show;
  End
 Else
  Begin
   Application.CreateForm(TChildMDIForm1,ChildMDIForm1); //Form'un başlığı yoksa Tekrar Creat olayı yapıyplıyor.
 End
Tüm yeni ChildMDIForm oluşturma kodlarını bu şekilde kullanıyorum..

ChildMDIForm'ların OnClose Eventlerindeki kodda aşağıdaki gibidir.!

Kod: Tümünü seç

procedure TChildMDIForm1.FormCreate(Sender: TObject);
begin
ChildMDIForm1.WindowState:=wsMaximized;
end;

procedure TChildMDIForm1.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
(Sender as TForm).Free;
end;
Kullanılan kodlar budur. Tek bir form'u açıp kapattımmı sürekli hiç bir problem yok birden fazla forumda gerçekleşiyor olay.. Mantıksal hiç bir hata tespit edemedim ben.

OnClose eventinde :

Action :=CaFree;
Destroyer;
Kodlarıda denendi sonuç ayın..

Bazı araştırmalarımdan ram bellek okuma hatası diyorlar ve ram yetersizliğinden kaynaklanabilir diyorlar. 4gb ddr2 800mhrz li bir makinede çalışıyorum.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
Kullanıcı avatarı
Murat DİCLE
Kıdemli Üye
Mesajlar: 702
Kayıt: 19 Nis 2006 04:12
Konum: İstanbul
İletişim:

Re: Çıkmaza sokan bir hata !

Mesaj gönderen Murat DİCLE »

ByDeniS yazdı:Toolbar buttonlarına tıklayınca uygulanan create yordamı !

Kod: Tümünü seç

 if ChildMDIForm1.Caption <> '' Then // Açılmaya çalışan fom'un başlığı eşit değilse Null'e bu forum açık demektir ve Show işlemini yapıyor.
  Begin
   ChildMDIForm1.Show;
  End
 Else
  Begin
   Application.CreateForm(TChildMDIForm1,ChildMDIForm1); //Form'un başlığı yoksa Tekrar Creat olayı yapıyplıyor.
 End
Henüz CREATE edilip edilmediğini bilmediğin bir formun CAPTION'una erişmeye çalışıyorsun. Güvenli olmayan bir yöntem. Hata buradan kaynaklanıyor.

Kod: Tümünü seç

 if ChildMDIForm1.Caption <> '' Then
Bu hatalı bir yaklaşımdır. Doğrusu aşağıdaki gibi olmalıdır.

Kod: Tümünü seç

 if Assigned(ChildMDIForm1) Then
Tabi burada şöyle bir soru doğuyor: Aynı tipteki form'dan birden fazla mı CREATE etmen gerekiyor. Eğer öyleyse aynı tipteki (TChildMDIForm1) bir formu sürekli ChildMDIForm1 tutamacıyla CREATE Etmen de hatalıdır. TChildMDIForm1 tipindeki bir formdan birden fazla create etmen gerektiğinde her create için ayrı bir tutamaç gerekecektir.
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

@Murat DİCLE

if döngüsü ile eğer form yoksa captionda yoktur, bundan yola çıkara if Form.Caption <> '' Then kodunu kullandım. Eğer form varsa zaten caption vadır bu demektirki else kısmını işletmek. Bir form'u bir kere create ediyor. Destroyer yada Actiın:=CaFree; ile formlar kapatılıp tekrar açıldıktan sonra bu hata meydana geliyor.

Aynı form'dan tekrar tekrar creat ettirmıyorum.

Form1
Form2
Form3 hepsini creat ayrı ayrı butonlarla yapıyorum. Creat edilmiş bir Form bir daha creat edilmiyor taki kapatılanakadar. sonrası aynı problem devam ediyor.. Verdiğiniz koddada aynı problemi yaşıyorum bu seferki farklılık.

1. Ya form'u hiç açmıyor.
2. Abstract Error diye hata veriyor.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

Birde formlar ilk açıldıktan sonra kapatıldımı bir daha açılmıyor.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
nightwolfcem
Üye
Mesajlar: 32
Kayıt: 02 Eki 2008 02:55

Re: Çıkmaza sokan bir hata !

Mesaj gönderen nightwolfcem »

Eğer form yoksa captionda yoktur deyip formun captionunu kontrol ettirmenin doğru bir yöntem olduğunu sanmıyorum.beden olduğunu açıklayım;
Farketmiştirsin Formlar da diğer nesneler gibi oluşturulduktan sonra global(genel) bir değişkene aktarılır .
Örn)
Form1, Tform1 sınıfından türelien nesneyi gösteren interface kısmında
var
Form1: TForm1; şeklinde tanımlanmış bir değişkendir.
Form1.Caption ise bu nesnenin caption değişkeninin verisine ulaşır.
Form1 degişkeninin gösterdiği nesneyi(Formu) yok ettiğiniz zaman Form1 değişkeni artık olmayan bir nesneyi göstericektir.En azından gösterdiği yerde artık o nesne bulunmuycaktır.
sizinde Form1.Caption sorgunuz hedef bulunamadığından büyük ihtimal hafıza erişim hatası olarak geri dönücektir .
Yok edilme ihtimali olan nesnelerin alanlarına ulaşırken önce o nesnenin olup olmadığına bakmak daha doğru.
if (ChildMDIForm1 <>nil)and (ChildMDIForm1.Caption <> '') Then gibi bu sadece bir örnek.
sizin yapmanız gereken kontrol sadece ChildMDIForm1 in gösterdiği nesnenin hala var olup olmadığı, olmalı ; if ChildMDIForm1 <>nil then gibi
Birde önemli nokta şu var , formun yok edilmesi ChildMDIForm1 hala bir hedefi gösterdiği gerçeğini değiştirmez ChildMDIForm1 yanlışta olsa hafızada aynı yeri göstermiye devam eder ChildMDIForm1 <>nil sorgunuz .onaydan geçsede ChildMDIForm1.caption, işaret edilen nesne yerinde olmadığıdan hata vercektir.
Çözüm Formların yok edildikten sonra değişnine de nil değeri atanmasıdır. Kodlar şöyle olcaktır.

Kod: Tümünü seç

//
if ChildMDIForm1 <> nil Then // Açılmaya çalışan fom'un başlığı eşit değilse Null'e bu forum açık demektir ve Show işlemini yapıyor.
  Begin
   ChildMDIForm1.Show;
  End
Else
  Begin
   Application.CreateForm(TChildMDIForm1,ChildMDIForm1); //Form'un başlığı yoksa Tekrar Creat olayı yapıyplıyor.
end;
//

procedure TChildMDIForm1.FormCreate(Sender: TObject);
begin
ChildMDIForm1.WindowState:=wsMaximized;
end;

procedure TChildMDIForm1.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
(Sender as TForm).Free;
ChildMDIForm1:=nil;
end;
Aşağıdaki kod delphinin nesneleri yok etmek için kullandığı yöntem
Hem nesneyi yok ediyor hemde işaretcisinin değerine nil atıyor.En sağlıklı ve kullanılması gereken yöntem budur.
free metodu yerine Freeandnil kullanılması daha uygun.

Kod: Tümünü seç

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;
Yukardaki kodu araştırırken şunuda farkettimki delphinin yeni sürümlerinde Freeandnil metoduna daha önem verilmiş.
Delphi 2007 de

Kod: Tümünü seç

destructor TScrollingWinControl.Destroy;
begin
  FHorzScrollBar.Free;
  FVertScrollBar.Free;
  inherited Destroy;
end;
Delphi2010 da

Kod: Tümünü seç

destructor TScrollingWinControl.Destroy;
begin
  FreeAndNil(FHorzScrollBar);
  FreeAndNil(FVertScrollBar);
  inherited Destroy;
end;
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

@nightwolfcem

Öncelikle cevabınız için teşekkür ederim. Hala bir sonuç alamadım ama daha farklı bir yola için ışık tuttu. İlginiz için teşekkürler.

Birde Caption olayını birdaha vurgulamak istiyorum. Burada ben caption kullandığımda problem çıkmıyor. İşe yarıyor yaradığı gibi problemde yaşatmıyor. Olay Destroyer yada Free yapıldıktan sonraki tekrarlanan creat olayıydı. Burada problem çıkıyor. Çok teşekkür ederim iyi çalışmalar.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
nightwolfcem
Üye
Mesajlar: 32
Kayıt: 02 Eki 2008 02:55

Re: Çıkmaza sokan bir hata !

Mesaj gönderen nightwolfcem »

CAption olayında sorun cıkmaması sırun yok anlamına gelmez sorun çıkmamasının nedenini aşağıda açıklamaya çalıştım.

formları yok ederken close olayındaki action değişkeninin görevi aklıma geldi .
action:=cafree ataması ile form yok ediliyordu. Delphinin kendi kodlarından bu atamanın nasıl bir etki yaptığına baktım.
PostMessage(Handle, CM_RELEASE, 0, 0); şeklinde bir fonksiyonu çağırıyordu.
Bunun anlamı formun oluşturulduğu pencereye yok edilme komutunun gönderilmesiydi. Delphi ise windows penceresinin yok edilmesine ek olarak CMrelease messajını aşağıdaki gibi yönetiyordu.

Kod: Tümünü seç

procedure TCustomForm.CMRelease;
begin
  Free;
end;
yani pencere yok edildiğinde Formun nesneside yok ediyordu. Bu durumda Formun onclose olayına
action:=cafree yazmamız hem formun hemde ona ait pencerenin yok edilmesiydi.

action:=cafree atamasını yapmadan formu yok etmeniz sadece form nesnesinin yok edilmesini sağlar. oluşturulan pencereye ait veriler hafızada kalır.
Senin yazdığın koddaki ChildMDIForm1.caption un hata vermemesinin nedenide oluşturulan pencerenin hala var olmasından kaynaklıydı.
Dediğimi daha iyi anlamak forma ait bir değişken tanımla ve kapama olayından sonra hem captionu hemde tanımladığınız değişkeni okutun.
caption doğru sonucu verirken forma ait tanımlanan değişken hata vericek yada yanlış bilgi vericektir.
Neyse fazla uzatmıyım ben direk kullanmanız gereken şekli yazıcam ve büyük ihtimal sorununuz çözülecek.
Yok Etmek İçin :

Kod: Tümünü seç

procedure TChildMDIForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
action:=cafree;
ChildMDIForm1:=nil;
end;
Bu arada isterseniz action:=cafree yi ekledikten aşağıdaki kodu yazmadan önce sizin caption hala doğru veriyi alıyormu kontrol edin ;)
Oluşturmak için

Kod: Tümünü seç

if ChildMDIForm1 <> nil Then // Açılmaya çalışan fom'un başlığı eşit değilse Null'e bu forum açık demektir ve Show işlemini yapıyor.
  Begin
   ChildMDIForm1.Show;
  End
Else
  Begin
   Application.CreateForm(TChildMDIForm1,ChildMDIForm1); //Form'un başlığı yoksa Tekrar Creat olayı yapıyplıyor.
end;
Kullanıcı avatarı
ByDeniS
Üye
Mesajlar: 144
Kayıt: 03 Oca 2009 12:24
Konum: My Computer

Re: Çıkmaza sokan bir hata !

Mesaj gönderen ByDeniS »

@nightwolfcem

Tekrar teşekkür ediyorum.

İlk olarak form'da konuyu açmadan önce denediğin kodlar
Action:=CaFree; , Free; , Destroyer; (Sender as TForm).Free;

OnClose eventinde bu kodları teker teker denedim. İlk açılışta create ediyor sonra onclosede yazdığım komutları işletiyor. Tekrar butona tıkladığımda Benim hatalı kodum ile Caption <> '' Then olayında form olmadığından Tekrar Crete olayına geçiyor. İşte burada hata veriyor.

Neyseki problemi daha farklı bir yöntemle aştım.

Buradaki caption özelliğine gelince benim hatalı olan if döngüsünde kullandığım kod. Bu kodu bu şekilde kullanmamın amacı; Probramla dillerinde Hiç olmayan değer null olarak geçer. Bazı problama dillerinde null = aynı zaman '' ama bazı programlama dillerindede null != yada <> '' burada hata yapmış olabilirim. Bir çok programlama dili kafamda karıştığı için delphide yeni olduğum için böyle bir hata oluşabilir. Ama delphide '' eşitmidir null'e ve null değerleri eşitmidir. Yoksa yada eşit değilseye bunu bilemiyorum.

Koddaki düşünce ve yazma yolum şudur.

Forum yoksa caption'u eşittir null'e yani ''
Ama form varsa caption eşit değildir '' oradaki işlettiğim if döngüsü buydu yada işletmeye çalıştığım. Hatalı olabilir sebebide yukarıda belirttiğim dil karışıklığıdır.

Sorunum çözülmüştür. Tekrar teşekkür ederim ilginiz için.
·•· Bilgi Güçtür ! Bu Gücü Hisset ! ·•·
Kullanıcı avatarı
Murat DİCLE
Kıdemli Üye
Mesajlar: 702
Kayıt: 19 Nis 2006 04:12
Konum: İstanbul
İletişim:

Re: Çıkmaza sokan bir hata !

Mesaj gönderen Murat DİCLE »

ByDeniS yazdı:@nightwolfcem

Tekrar teşekkür ediyorum.

İlk olarak form'da konuyu açmadan önce denediğin kodlar
Action:=CaFree; , Free; , Destroyer; (Sender as TForm).Free;

OnClose eventinde bu kodları teker teker denedim. İlk açılışta create ediyor sonra onclosede yazdığım komutları işletiyor. Tekrar butona tıkladığımda Benim hatalı kodum ile Caption <> '' Then olayında form olmadığından Tekrar Crete olayına geçiyor. İşte burada hata veriyor.

Neyseki problemi daha farklı bir yöntemle aştım.

Buradaki caption özelliğine gelince benim hatalı olan if döngüsünde kullandığım kod. Bu kodu bu şekilde kullanmamın amacı; Probramla dillerinde Hiç olmayan değer null olarak geçer. Bazı problama dillerinde null = aynı zaman '' ama bazı programlama dillerindede null != yada <> '' burada hata yapmış olabilirim. Bir çok programlama dili kafamda karıştığı için delphide yeni olduğum için böyle bir hata oluşabilir. Ama delphide '' eşitmidir null'e ve null değerleri eşitmidir. Yoksa yada eşit değilseye bunu bilemiyorum.

Koddaki düşünce ve yazma yolum şudur.

Forum yoksa caption'u eşittir null'e yani ''
Ama form varsa caption eşit değildir '' oradaki işlettiğim if döngüsü buydu yada işletmeye çalıştığım. Hatalı olabilir sebebide yukarıda belirttiğim dil karışıklığıdır.

Sorunum çözülmüştür. Tekrar teşekkür ederim ilginiz için.
Bak Delphi'de Form Label vb. şeylerin bir tutamacı (pointer) vardır. Program ilk çalıştığında formun pointer'i NIL değerindedir. Bir formu create ettiğinde form için bir bellek ayrılır ve pointer'a ayrılan belleğin başlangıç adresi atanır. Sen formu caFree veya Destroy ile yok ettiğinde pointer hala o adresi gösteriyor olacaktır.

İkince kez sen IF ile o formun CAPTION'u var mı dediğinde şansa bağlı olarak -eğer bellek üzerine başka bir şey yazılmamışsa- CAPTION sorgunda hata olmayabilir. Bu doğru bir yaklaşım değildir. Madem ki delphi'de yenisin. Bu konuyu öğrenmen gerek, böylece sorunu kökten çözmüş olursun. Sol elinle sağ kulağını tutup sağ elinle sol kulağı tutarak program yazılamıyor maalesef.

Kaldı ki ben NIL olup olmadığını kontrol ederek yapardırm. MDIChild Formun OnCloce event'ına PostMessage ile ana forma mesaj çeker, beni FREE ve pointer'imi NIL yap derdim. Hiç denemedim ama formun Destroy event'ında Form1 := nil demekte çözüm olabilir. Böylece IF Form1 <> nil then Form1.Show else Form1 := TForm1.create(self); ile işini yapabilirsin.
qamyoncu
Üye
Mesajlar: 266
Kayıt: 12 Tem 2008 04:30

Re: Çıkmaza sokan bir hata !

Mesaj gönderen qamyoncu »

Sayısını bilmediğim sayıda ChildForm ile çalışıyorum. Photoshoptaki her bir çalışma gibi düşünebilirsiniz. Kullanıcı istediği kadar açabiliyor. Ve bu çalışmaların isimleri Pencere adlı MainMenu iteminde sıralanıyor. Buradan istediğini seçip onu aktif yapabiliyor. Ve ChildForm'un exit düğmesine basınca form yokediliyor ve Pencere Menüsünden adı kaldırılıyor.

Sizin yaptığınızdan tek farklı noktası; ben her seferinde farklı bir ChildForm Create ederken siz hep aynı formu create ediyorsunuz. Nedenini bilmiyorum ancak sorun buradan kaynaklanıyor. Tavsiye edilmeyecek bir çözüm olsa da sorunu aşma açısından yardımcı olabilir:

Kod: Tümünü seç

CreateChildForm('ChildForm1');

Kod: Tümünü seç

procedure TForm1.CreateChildForm(const childName : string; X, Y: Integer);
var
  Child: TForm;
begin
  Child := TForm.Create(Application);
  Child.Width:=400;
  Child.Height:=247;
  Child.FormStyle:=FsMDIChild;
  Child.WindowState:=WsMaximized;
  Child.Caption := childName;
  Child.AutoScroll:=True;
  Child.OnClose:=Form4.OnClose;
//extradan create edip değerlerini ataman gereken bileşenler formunun üstündeki bileşenler olacak. Biraz hammallık tabii.

Kod: Tümünü seç

procedure TForm4.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if (Sender as TForm).Name<>'Form1' then
   (Sender as TForm).Free;
end;
Batuhan TAŞDÖVEN
'Yükseldikçe küçülen bir uçurtma..'
Cevapla