XML Olusturmada OutOf Memory Hatası

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
mert_37
Üye
Mesajlar: 35
Kayıt: 13 Şub 2014 02:53

XML Olusturmada OutOf Memory Hatası

Mesaj gönderen mert_37 » 02 Eki 2019 07:08

Selam Arkadaşlar bugünlerde programlarla haşır neşirim.
Bir veritabanım var bilgikeri bu veritabanına cekiyorum. Ve bir xml Dosya Oluşturuyorum.
Bir kaç defa sorunsuz çalışıyor. Bir müddet sonra OutOf Memory uzun bir hata veriyor. Memory taşıyor
Bu memory boşaltmam gerek. Kod aşşagıdakigibidir. Bu tip çalışmaları yapmış biri varsa lütfen yardım.

Tyy / Except ben ekleme yaptım hatayı keserrim diye ama mumkun olmadı. Buraya her geldiğimde
bu alanı temizlemem gerek. Temizleniyorda ...Ama hafızada ne kalıyorda hemen outof memory diyik çakılıyor. :)
Ve memory nasıl boşaltırım... Saygılar...

Try
TempString := '';
TempString := TempString + '<xmldata kod="'+'0001679'+'" ' ;
TempString := TempString + 'Tarih="'+tar1+' '+time1+'" ';
TempString := TempString + Version ="6.0"> ' ;
DataSet.First ;
sira:=0; si:='';
While not Dataset.eof do begin
sira:=sira+1; si:=floattostr(sira);
TempString := TempString +'<PRO>' ;
TempString := TempString +' <SiraNo>'+si+'</SiraNo>' ;
TempString := TempString +' <Id_no>'+Dataset.FieldByName('Id').AsString+'</Id_no>' ;
TempString := TempString +'</PRO>' ;
Dataset.next ;
end ;
TempString := TempString + '</xmldata>' ;
xx := STRMD5(TempString);
WriteString(Stream,'<?xml version="1.0" encoding="iso-8859-9" ?> ');
WriteString(Stream,'<?hash '+xx+'?>');
WriteString(Stream,TempString);
stream.CleanupInstance;
except
on E : Exception do begin // ShowMessage('Başlantı Hatası : ' + E.Message);
TempString := '';
stream.CleanupInstance;
exit;
end;
end;

ertank
Üye
Mesajlar: 1241
Kayıt: 11 Eyl 2015 11:45

Re: XML Olusturmada OutOf Memory Hatası

Mesaj gönderen ertank » 02 Eki 2019 10:19

Merhaba,

Paylaştığınız kod hafıza kaçağı veya neden sürekli hafıza kullanımı artıyor sorunuzu cevaplamak için yeterli değil. Delphi içine yapıştırınca derlenebilir bir kod paylaşır iseniz sorunu bulmaya yardımcı olmak mümkün olabilir.

Bununla birlikte kullandığınız TStream türevinin ne olduğunu bilmeden;

Kod: Tümünü seç

Stream.CleanupInstance;
kullanım amacınızı anlayamadım. Sizin normalde

Kod: Tümünü seç

Stream.Clear();
şeklinde kullanmanız yeterli olacaktır.

Son olarak, olası hafıza kaçakları için Program->View Source menü seçeneği ile gelen yerde begin ifadesinden sonra ilk satıra

Kod: Tümünü seç

ReportMemoryLeaksOnShutdown := True;
ifadesini ekler iseniz uygulamayı kapattığınızda *eğer var ise* hafıza kaçağınız olduğunu size bildirecektir. Hafıza kaçağı yok ise bir mesaj gelmeyecektir.

mert_37
Üye
Mesajlar: 35
Kayıt: 13 Şub 2014 02:53

Re: XML Olusturmada OutOf Memory Hatası

Mesaj gönderen mert_37 » 03 Eki 2019 02:07

Öncelikle Cevap için teşekkürler...
Program cok büyük..Hepsini kopyalamam bunaltıcı olur ...Strim DataSetToXML
Buradaki SourceBuffer standard değeri ne olabilir acaba. Bir xml de en fazla 1000 Kayıt olur.
Ayrıca
Delphi 7 kullanıyorum burada Stream.Clear(); Gecersiz..
Ancak
stream.CleanupInstance;
Stream.FreeInstance;
Stream.Free;
// Stream.Clear(); Kabul etmiyor...

Stream

procedure DatasetToXML(Dataset: TDataSet; FileName: string);
var
Stream: TFileStream;
bkmark: TBookmark;
i: Integer;
begin
Stream := TFileStream.Create(FileName, fmCreate);
SourceBuffer := StrAlloc(256000000);
WriteFileBegin(Stream, Dataset);

with DataSet do begin
DisableControls;
bkmark := GetBookmark;
First;

{write a title row}
WriteRowStart(Stream, True);
for i := 0 to FieldCount - 1 do
WriteData(Stream, nil, Fields.DisplayLabel);
{write the end of row}
WriteRowEnd(Stream, True);

while (not EOF) do begin
WriteRowStart(Stream, False);
for i := 0 to FieldCount - 1 do
WriteData(Stream, Fields, GetFieldStr(Fields));
{write the end of row}
WriteRowEnd(Stream, False);
Next;
end;

GotoBookmark(bkmark);
EnableControls;
end;
WriteFileEnd(Stream);
Stream.Free;
StrDispose(SourceBuffer);
end;

ertank
Üye
Mesajlar: 1241
Kayıt: 11 Eyl 2015 11:45

Re: XML Olusturmada OutOf Memory Hatası

Mesaj gönderen ertank » 03 Eki 2019 07:51

Merhaba,

Öncelikle bazılarında kati kural olarak, kural olmayanlarda da her bir programlama dili için genel kabul görmüş kod yazma formatı vardır. Paylaştığınız kodlarda blok kısımlarını ayırd etmek mümkün olmuyor. Bütün kod 1 numaralı kolondan başlıyor ve kodu okuması daha zor oluyor. begin..end arası, try..finally arası vb blok içinde kalan kodları minimum iki karakter boşluk vererek daha içeriden yazmanızda fayda var.

Ayrıca, kod örneklerinizi benim aşağıda yaptığım gibi code ve /code blokları içine yazmanız halinde okunması daha da kolay olan sabit genişlikli font ile ekranda gösterilecektir.

Paylaştığınız kod ile ilgili olarak. Neden yaklaşık 244MiB hafıza ayırdığınızı anlamadım. TFileStream kullanmanın amacı büyük boyutlu dosyalarda yüksek hafıza ihtiyacını ortadan kaldırmaya yöneliktir.

Bunun dışında nesneleri oluşturduktan sonra hafıza kaçağını engellemeye yönelik olarak try..finally bloğu içinde güvene almamışsınız. Arada yaptığınız işlemerlde bir hata oluşması durumunda bu hafıza kaçağına sebep olacaktır. Aynı konu StrAlloc() için de geçerli.

Sorunuzla ilgili emin olmamakla birlikte XML dosyasını UTF-8 olarak yazmak için bu şekilde bir kod yazdığınızı düşünüyorum. Kodunuzu daha pratik hale getirmek için Delphi 7 içindeki klasik string veri türünü ve ek bir prosedürü kullanarak yine istediğinizi daha basit şekilde elde etmeniz mümkün olabilir.

Kod: Tümünü seç

  procedure ConvertANSIFileToUTF8File(AInputFileName, AOutputFileName: string);
  var
    Strings: TStrings;
  begin
    Strings := TStringList.Create;
    try
      Strings.LoadFromFile(AInputFileName);
      Strings.Text := UTF8Encode(Strings.Text);
      Strings.SaveToFile(AOutputFileName);
    finally
      Strings.Free;
    end;
  end;

  procedure DatasetToXML(Dataset: TDataSet; FileName: string);
  var
    F: TextFile;
    bkmark: TBookmark;
    i: Integer;
  begin
    try
      AssignFile(F, Filename, CP_UTF8);
    except
      // Ne yapılması gerekiyor ise
      Exit;
    end;

    try
      ReWrite(F);
    except
      // Ne yapılması gerekiyor ise
      Exit;
    end;

    try
      WriteFileBegin(F, Dataset);

      with Dataset do
      begin
        DisableControls;
        bkmark := GetBookmark;
        First;

        { write a title row }
        WriteRowStart(F, True);
        for i := 0 to FieldCount - 1 do
          WriteData(F, nil, Fields.DisplayLabel);
        { write the end of row }
        WriteRowEnd(F, True);

        while (not EOF) do
        begin
          WriteRowStart(F, False);
          for i := 0 to FieldCount - 1 do
            WriteData(F, Fields, GetFieldStr(Fields));
          { write the end of row }
          WriteRowEnd(F, False);
          Next;
        end;
      end;
    finally
      WriteFileEnd(F);
      GotoBookmark(bkmark);
      EnableControls;
      CloseFile(F);
      ConvertANSIFileToUTF8File(Filename, Filename);
    end;
  end;
Mevcut kod olmadığı için yeniden düzenlenmesi gereken aşağıdaki prosedürleriniz için örnek kod hazırlayamadım
WriteFileBegin()
WriteRowStart()
WriteData()
WriteRowEnd()
WriteFileEnd()

mert_37
Üye
Mesajlar: 35
Kayıt: 13 Şub 2014 02:53

Re: XML Olusturmada OutOf Memory Hatası

Mesaj gönderen mert_37 » 09 Eki 2019 08:08

Cevap için teşekkür ederim...

Çok haklısınız Ertan bey Bu hafıza olayı 244 MB bireyre girmedim ama ben göremedim. SourceBuffer := StrAlloc(256000000); satırı 244 MB mi yapıyor. ?
Ben kısaca şöyle söylim. Bu örnek, derme çatma , kurcalaya kurcalaya biraz ezbere yaptığım bir çallışma.
ama uzun süre calıştı işimi de gördü.

Bu örneği bir yerde başka bir projede kullanmak istedim. Sorunda burada başladı.

Aslında biliyorum ya hafızayı arttıracam yada hafızada olup biteni tamamıyla silemem gerek.
Verdiğim komutlar işe yaramıyor. Bır şekile Out Of Memmory hatası veriyor ...
Hafızayı nasıl yükseltebilirim ? Atma olayından vazgeçtim.

mert_37
Üye
Mesajlar: 35
Kayıt: 13 Şub 2014 02:53

Re: XML Olusturmada OutOf Memory Hatası

Mesaj gönderen mert_37 » 09 Eki 2019 08:10


ertank
Üye
Mesajlar: 1241
Kayıt: 11 Eyl 2015 11:45

Re: XML Olusturmada OutOf Memory Hatası

Mesaj gönderen ertank » 10 Eki 2019 10:42

mert_37 yazdı:
09 Eki 2019 08:08
Cevap için teşekkür ederim...

Çok haklısınız Ertan bey Bu hafıza olayı 244 MB bireyre girmedim ama ben göremedim. SourceBuffer := StrAlloc(256000000); satırı 244 MB mi yapıyor. ?
Ben kısaca şöyle söylim. Bu örnek, derme çatma , kurcalaya kurcalaya biraz ezbere yaptığım bir çallışma.
ama uzun süre calıştı işimi de gördü.
Tam olarak 244,140625 MiB yapıyor.
mert_37 yazdı:
09 Eki 2019 08:08
Bu örneği bir yerde başka bir projede kullanmak istedim. Sorunda burada başladı.

Aslında biliyorum ya hafızayı arttıracam yada hafızada olup biteni tamamıyla silemem gerek.
Verdiğim komutlar işe yaramıyor. Bır şekile Out Of Memmory hatası veriyor ...
Hafızayı nasıl yükseltebilirim ? Atma olayından vazgeçtim.
Hafıza yükseltmenize gerek yok. Çok yüksek ihtimal ile kullandığınız kodun 244MiB hafıza ihtiyacı da yok. Size gönderdiğim örnek kodları inceler iseniz TFileStream yerine bu kod içindeki TextFile türünü kullanabilirsiniz.

Normalde her windows uygulamasının işletim sistemi tarafından bir maksimum hafıza kullanım limiti vardır. İçinde hata olan bir uygulama sistem kaynaklarının tamamını kullanıp sistemi kararsız hale getirmesini önlemek için bu limitler tanımlanmıştır. Windows 32bit uygulamalar için bu limit 2GB, Windows 64Bit uygulamalar için ise 16TiB limit vardır. Bu limitler bilgisayarda yüklü RAM miktarı bağımsızdır. Yani bilgisayarda 64BG ram dahi olsa 32Bit uygulama maksimum 2GB kısmını kullanabilir.

32Bit uygulamalar için 2GB limitini 4GB civarına çıkarmak için yöntemler mevcut. Ancak dediğim gibi, sizin uygulamanız için böyle bir ihtiyaç olacağına pek olasılık vermiyorum.

Cevapla