Tüm Platformlar için Hızlı Uygulama Geliştirme Kitabı... Delphi

Konuyu Paylaş : facebook gplus twitter

Konuyu Oyla:
  • Derecelendirme: 3/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Sabitin Bellekte Kapladığı Miktar
#1
Merhaba,
Büyük projelerde belki yüzlerce hatta binlerce sabit kullanılır. Bu durumda bellek yönetimi son derece önem kazanmaktadır. Bir çoğumuz bu tip konulara dikkat etmesek de bilmenin faydalı olacağını düşünerek bir soru ile beyin fırtınası yaparak, bu kapsamda doğru yolu bulalım diyorum.

Örneğin 3 karakterim var ve bunu sabit olarak tanımlamak istiyorum. 

type
 TKullanıcıTanımlıBirDeğerDaha = (a, b, c);
 TKullanıcıTanımlıBirDeğerDahaTumu = set of TKullanıcıTanımlıBirDeğerDaha;
 TBirKüme = 'a' .. 'b';
 TBirKümeTüm = set of TBirKüme;

resourcestring
 resDeğer = 'abc';

const
 cnsDeğer1 = 'abc';
 cnsDeğer2: ShortString = 'abc';
 cnsDeğer3: String = 'abc';
 cnsDeğer4: AnsiString = 'abc';
 cnsDeğer5: WideString = 'abc';
 cnsDeğer6: TKullanıcıTanımlıBirDeğerDahaTumu = [a, b, c];
 cnsDeğer7: TBirKümeTüm = ['a', 'b', 'c'];
 cnsDeğer8: array [0 .. 2] of Char = ('a', 'b', 'c');
 cnsDeğer9: array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
 cnsDeğer10: array [0 .. 2] of WideChar = ('a', 'b', 'c');

  • Hangi tanımlama hafızada ne kadar yer kaplar? 
  • Delphi/Object Pascal ile bu tanımlamayı daha kaç farklı şekilde yapabilirim? 
  • Hangisi daha avantajlı ve hızlı olur? 
  • En az işleme tabi tutarak kullanabileceğim tip hangisi? 

Sabit veya değişken tanımlamaların rastgele yapılmaması ve bilinçli yapılmasının ne derece önemli olduğunu belirtir bir yazı paylaşıyorum.

Alıntı:4 Haziran 1996 — Ariane 5 Flight 501: Ariane 4 roketinin çalışma kodu Ariane 5’te yeniden kullanılmıştı. Fakat Ariane 5’in daha hızlı olan motoru, roketin uçuş bilgisayarındaki bir aritmetik işlemde bir hatanın ortaya çıkmasına yol açıyordu. Hata, bilgisayar ifadeleriyle, 64 bitlik ondalıklı sayıyı 16 bitlik işaretli tam sayıya dönüştüren kodda idi. Daha hızlı motor 64 bitlik sayıların Ariane 5’te, Ariane 4 de olduğundan daha büyük olmasına yol açıyor ve böylece sayısal taşma durumu yaratıyor, o da uçuş bilgisayarının çökmesini getiriyordu. Flight 501’in destek bilgisayarı çöktü, 0.05 saniye sonra da ana bilgisayar çöktü. Çöken bilgisayarlar sonucu, roketin ana işlemcisi motorlara aşırı güç yüklenmesine yol açtı ve roket, fırlatıldıktan 40 saniye sonra, parçalandı.

Bu ve buna benzer daha bir çok örnek var. : Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
While true do; Hayat döngüsü, kısır değildir! Yapılan bir yanlış, o döngünün dışına çıkmanızı sağlayacaktır.
WWW
Cevapla
#2
İşte bu ve buna benzer nedenlerden ötürü Low Level programlama olmazsa olmazlardandır.

Ayrıca aşağıdaki örneği inceleyebilirsiniz:

procedure TForm1.Button1Click(Sender: TObject);
const
 S1  : String = 'Deneme';
 A1  : AnsiString = 'Deneme';
 C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
 C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
 C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
 S2  = 'Deneme';
var
 Arr : array of Byte;
begin
 SetLength(Arr, 1024);

 ShowMessage('S1 Size:' + SizeOf(S1).ToString());
 ShowMessage('S2 Size:' + SizeOf(S2).ToString());
 ShowMessage('A1 Size:' + SizeOf(A1).ToString());

 ShowMessage('C1 Size:' + SizeOf(C1).ToString());
 ShowMessage('C2 Size:' + SizeOf(C2).ToString());
 ShowMessage('C3 Size:' + SizeOf(C3).ToString());

 ShowMessage('Arr Size:' + SizeOf(Arr).ToString());
 Arr := nil;
end;

String'lerin , dinamik dizilerin birer pointer olduğunu unutmayın Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#3
Selam, burada önemli olan hafızadaki kapladığı alan değilmidir? Tuğrul hocam verdiğiniz örneğe göre size larını görebiliyoruz, hemen hemen aynı hepsi. Ben biraz değiştirip şöyle bişi yaptım ama burda dikkatimi çeken bişi oldu.
procedure TForm1.Button1Click(Sender: TObject);
const
S1  : String = 'Deneme';
A1  : AnsiString = 'Deneme';
C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
S2  = 'Deneme';
S4  = 'Deneme';
var
Arr1 : array of Byte;
S3 : STRING;
Arr2 : array of Byte;
begin

SetLength(Arr1, 1024);
SetLength(Arr2, 1024);
S3:='DenemeDeneme3';

MEMO1.Lines.Add('-----------------------------------');


MEMO1.Lines.Add(
   'S1 : Address: ' + IntToStr (Integer (S1)) +
   ', Length: ' + IntToStr (Length (S1)) +
   ', References: ' + IntToStr (PInteger (Integer (S1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S1)) +
   ', Value: ' + S1);

MEMO1.Lines.Add(
   'S2 : Address: ' + IntToStr (Integer (S2)) +
   ', Length: ' + IntToStr (Length (S2)) +
   ', References: ' + IntToStr (PInteger (Integer (S2) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S2)) +
   ', Value: ' + S2);

MEMO1.Lines.Add(
   'S3 : Address: ' + IntToStr (Integer (S3)) +
   ', Length: ' + IntToStr (Length (S3)) +
   ', References: ' + IntToStr (PInteger (Integer (S3) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S3)) +
   ', Value: ' + S3);

MEMO1.Lines.Add(
   'S4 : Address: ' + IntToStr (Integer (S4)) +
   ', Length: ' + IntToStr (Length (S4)) +
   ', References: ' + IntToStr (PInteger (Integer (S4) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S4)) +
   ', Value: ' + S4);

MEMO1.Lines.Add(
   'A1 : Address: ' + IntToStr (Integer (A1)) +
   ', Length: ' + IntToStr (Length (A1)) +
   ', References: ' + IntToStr (PInteger (Integer (A1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(A1)) +
   ', Value: ' + A1);

MEMO1.Lines.Add(
   'C1 : Address: ' + IntToStr(Integer(@C1)) +
   ', Length: ' + IntToStr (Length (C1)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(C1)) +
   ', Value: ' + C1);

MEMO1.Lines.Add(
   'C2 : Address: ' + IntToStr(Integer(@C2)) +
   ', Length: ' + IntToStr (Length (C2)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(C2)) +
   ', Value: ' + C2);

MEMO1.Lines.Add(
   'C3 : Address: ' + IntToStr(Integer(@C3)) +
   ', Length: ' + IntToStr (Length (C3)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(C3)) +
   ', Value: ' + C3);

MEMO1.Lines.Add(
   'Arr1 : Address: ' + IntToStr(Integer(@Arr1)) +
   ', Length: ' + IntToStr (Length (Arr1)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(Arr1)) +
   ', Value: ' + INTTOSTR(Arr1[0]));

MEMO1.Lines.Add(
   'Arr2 : Address: ' + IntToStr(Integer(@Arr2)) +
   ', Length: ' + IntToStr (Length (Arr2)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(Arr2)) +
   ', Value: ' + INTTOSTR(Arr2[0]));

Arr1 := nil;
Arr2 := nil;
end;
kodun sonucu (tanımlamalar ile birlikte yazdım);
const
 S1  : String = 'Deneme';
 A1  : AnsiString = 'Deneme';
 C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
 C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
 C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
 S2  = 'Deneme';
 S4  = 'Deneme';
var
 Arr1 : array of Byte;
 S3 : STRING;
 Arr2 : array of Byte;
begin

 SetLength(Arr1, 1024);
 SetLength(Arr2, 1024);
S3:='DenemeDeneme3';
-----------------------------------
S1 : Address: 4520904, Length: 6, References: -1, Size: 4, Value: Deneme
S2 : Address: 9779496, Length: 6, References: 1, Size: 4, Value: Deneme ****************
S3 : Address: 4522824, Length: 13, References: -1, Size: 4, Value: DenemeDeneme3
S4 : Address: 9780912, Length: 6, References: 1, Size: 4, Value: Deneme ****************
A1 : Address: 4520920, Length: 6, References: -1, Size: 4, Value: Deneme
C1 : Address: 4529580, Length: 3, References: . , Size: 3, Value: abc
C2 : Address: 4529584, Length: 3, References: . , Size: 3, Value: abc
C3 : Address: 4529588, Length: 3, References: . , Size: 6, Value: abc
Arr1 : Address: 1308200, Length: 1024, References: . , Size: 4, Value: 0 ********************
Arr2 : Address: 1308192, Length: 1024, References: . , Size: 4, Value: 0 *********************

burda dikkatimi çeken şu oldu, string ansistring char vs. hafızanın belli bir bölgesinden tahsis edildi, arrayler farklı bir bölgeden, resource lar farklı bir bölgeden, yada banamı öyle denk geldi, birkaç deneme yaptım hep benzer sonuçlar aldım, bunun bir anlamı varmıdır?  ( * işareti ile işaretlediğim adresler )
Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
WWW
Cevapla
#4
(21-09-2016, Saat: 12:19)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Olİşte bu ve buna benzer nedenlerden ötürü Low Level programlama olmazsa olmazlardandır.

Ayrıca aşağıdaki örneği inceleyebilirsiniz:

procedure TForm1.Button1Click(Sender: TObject);
const
 S1  : String = 'Deneme';
 A1  : AnsiString = 'Deneme';
 C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
 C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
 C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
 S2  = 'Deneme';
var
 Arr : array of Byte;
begin
 SetLength(Arr, 1024);

 ShowMessage('S1 Size:' + SizeOf(S1).ToString());
 ShowMessage('S2 Size:' + SizeOf(S2).ToString());
 ShowMessage('A1 Size:' + SizeOf(A1).ToString());

 ShowMessage('C1 Size:' + SizeOf(C1).ToString());
 ShowMessage('C2 Size:' + SizeOf(C2).ToString());
 ShowMessage('C3 Size:' + SizeOf(C3).ToString());

 ShowMessage('Arr Size:' + SizeOf(Arr).ToString());
 Arr := nil;
end;

String'lerin , dinamik dizilerin birer pointer olduğunu unutmayın Wink

2yw70vm.jpg

Char ve WideChar 2 Byte iken neden AnsiChar 1 Byte?
While true do; Hayat döngüsü, kısır değildir! Yapılan bir yanlış, o döngünün dışına çıkmanızı sağlayacaktır.
WWW
Cevapla
#5
(21-09-2016, Saat: 15:11)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Ol
(21-09-2016, Saat: 12:19)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye Olİşte bu ve buna benzer nedenlerden ötürü Low Level programlama olmazsa olmazlardandır.

Ayrıca aşağıdaki örneği inceleyebilirsiniz:

procedure TForm1.Button1Click(Sender: TObject);
const
 S1  : String = 'Deneme';
 A1  : AnsiString = 'Deneme';
 C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
 C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
 C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
 S2  = 'Deneme';
var
 Arr : array of Byte;
begin
 SetLength(Arr, 1024);

 ShowMessage('S1 Size:' + SizeOf(S1).ToString());
 ShowMessage('S2 Size:' + SizeOf(S2).ToString());
 ShowMessage('A1 Size:' + SizeOf(A1).ToString());

 ShowMessage('C1 Size:' + SizeOf(C1).ToString());
 ShowMessage('C2 Size:' + SizeOf(C2).ToString());
 ShowMessage('C3 Size:' + SizeOf(C3).ToString());

 ShowMessage('Arr Size:' + SizeOf(Arr).ToString());
 Arr := nil;
end;

String'lerin , dinamik dizilerin birer pointer olduğunu unutmayın Wink

2yw70vm.jpg

Char ve WideChar 2 Byte iken neden AnsiChar 1 Byte?

Üstad, Delphi'nin 2009 sürümünden sonra, yani Delphi Unicode desteğinden sonra; Char = WideChar oldu, yani Char artık 2 byte. Dolayısı ile bir byte'lık eski karakterler AnsiChar ve bir byte'lık karakter dizileri de AnsiString üzerinden yürüyor.

(21-09-2016, Saat: 14:47)esistem Adlı Kullanıcıdan Alıntı: Linkleri Görebilmeniz İçin Giriş yap veya Üye OlSelam, burada önemli olan hafızadaki kapladığı alan değilmidir? Tuğrul hocam verdiğiniz örneğe göre size larını görebiliyoruz, hemen hemen aynı hepsi. Ben biraz değiştirip şöyle bişi yaptım ama burda dikkatimi çeken bişi oldu.
procedure TForm1.Button1Click(Sender: TObject);
const
S1  : String = 'Deneme';
A1  : AnsiString = 'Deneme';
C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
S2  = 'Deneme';
S4  = 'Deneme';
var
Arr1 : array of Byte;
S3 : STRING;
Arr2 : array of Byte;
begin

SetLength(Arr1, 1024);
SetLength(Arr2, 1024);
S3:='DenemeDeneme3';

MEMO1.Lines.Add('-----------------------------------');


MEMO1.Lines.Add(
   'S1 : Address: ' + IntToStr (Integer (S1)) +
   ', Length: ' + IntToStr (Length (S1)) +
   ', References: ' + IntToStr (PInteger (Integer (S1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S1)) +
   ', Value: ' + S1);

MEMO1.Lines.Add(
   'S2 : Address: ' + IntToStr (Integer (S2)) +
   ', Length: ' + IntToStr (Length (S2)) +
   ', References: ' + IntToStr (PInteger (Integer (S2) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S2)) +
   ', Value: ' + S2);

MEMO1.Lines.Add(
   'S3 : Address: ' + IntToStr (Integer (S3)) +
   ', Length: ' + IntToStr (Length (S3)) +
   ', References: ' + IntToStr (PInteger (Integer (S3) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S3)) +
   ', Value: ' + S3);

MEMO1.Lines.Add(
   'S4 : Address: ' + IntToStr (Integer (S4)) +
   ', Length: ' + IntToStr (Length (S4)) +
   ', References: ' + IntToStr (PInteger (Integer (S4) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(S4)) +
   ', Value: ' + S4);

MEMO1.Lines.Add(
   'A1 : Address: ' + IntToStr (Integer (A1)) +
   ', Length: ' + IntToStr (Length (A1)) +
   ', References: ' + IntToStr (PInteger (Integer (A1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(A1)) +
   ', Value: ' + A1);

MEMO1.Lines.Add(
   'C1 : Address: ' + IntToStr(Integer(@C1)) +
   ', Length: ' + IntToStr (Length (C1)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(C1)) +
   ', Value: ' + C1);

MEMO1.Lines.Add(
   'C2 : Address: ' + IntToStr(Integer(@C2)) +
   ', Length: ' + IntToStr (Length (C2)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(C2)) +
   ', Value: ' + C2);

MEMO1.Lines.Add(
   'C3 : Address: ' + IntToStr(Integer(@C3)) +
   ', Length: ' + IntToStr (Length (C3)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(C3)) +
   ', Value: ' + C3);

MEMO1.Lines.Add(
   'Arr1 : Address: ' + IntToStr(Integer(@Arr1)) +
   ', Length: ' + IntToStr (Length (Arr1)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(Arr1)) +
   ', Value: ' + INTTOSTR(Arr1[0]));

MEMO1.Lines.Add(
   'Arr2 : Address: ' + IntToStr(Integer(@Arr2)) +
   ', Length: ' + IntToStr (Length (Arr2)) +
   ', References: . ' +// IntToStr (PInteger (Integer (C1) - 8)^) +
   ', Size: ' + IntToStr(SizeOf(Arr2)) +
   ', Value: ' + INTTOSTR(Arr2[0]));

Arr1 := nil;
Arr2 := nil;
end;
kodun sonucu (tanımlamalar ile birlikte yazdım);
const
 S1  : String = 'Deneme';
 A1  : AnsiString = 'Deneme';
 C1  : array [0 .. 2] of Char = ('a', 'b', 'c');
 C2  : array [0 .. 2] of AnsiChar = ('a', 'b', 'c');
 C3  : array [0 .. 2] of WideChar = ('a', 'b', 'c');
resourcestring
 S2  = 'Deneme';
 S4  = 'Deneme';
var
 Arr1 : array of Byte;
 S3 : STRING;
 Arr2 : array of Byte;
begin

 SetLength(Arr1, 1024);
 SetLength(Arr2, 1024);
S3:='DenemeDeneme3';
-----------------------------------
S1 : Address: 4520904, Length: 6, References: -1, Size: 4, Value: Deneme
S2 : Address: 9779496, Length: 6, References: 1, Size: 4, Value: Deneme ****************
S3 : Address: 4522824, Length: 13, References: -1, Size: 4, Value: DenemeDeneme3
S4 : Address: 9780912, Length: 6, References: 1, Size: 4, Value: Deneme ****************
A1 : Address: 4520920, Length: 6, References: -1, Size: 4, Value: Deneme
C1 : Address: 4529580, Length: 3, References: . , Size: 3, Value: abc
C2 : Address: 4529584, Length: 3, References: . , Size: 3, Value: abc
C3 : Address: 4529588, Length: 3, References: . , Size: 6, Value: abc
Arr1 : Address: 1308200, Length: 1024, References: . , Size: 4, Value: 0 ********************
Arr2 : Address: 1308192, Length: 1024, References: . , Size: 4, Value: 0 *********************

burda dikkatimi çeken şu oldu, string ansistring char vs. hafızanın belli bir bölgesinden tahsis edildi, arrayler farklı bir bölgeden, resource lar farklı bir bölgeden, yada banamı öyle denk geldi, birkaç deneme yaptım hep benzer sonuçlar aldım, bunun bir anlamı varmıdır?  ( * işareti ile işaretlediğim adresler )

Evet vardır üstad. Normalde tanımladığın local değişkenler PE/PE+'ın code section'unda; resource'lar ise şimdi adını anımsayamadığım başka bir section'da yer alıyorlar. Dolayısı ile farklı lokasyondalar. Ayrıca, local değişkenler Stack'da; global değişkenler Heap'de kendilerine yer bulurlar. Tahsisat hafızanın farklı lokasyonları üzerinde yapılır. Tabii burada detaylara tam haiz olabilmek için Delphi'nin Memory Manager'ı & FastMM hususunda da bilgimiz olması gerekir. Yanlış hatırlamıyorsam eğer; GetMem.inc dosyası içinden ilgili işlemleri takip edebilirsiniz; ama epeyce karışık olduğunu hatırlıyorum Wink
Mal sahibi, mülk sahibi
Hani bunun ilk sahibi ?
Mal da yalan mülk de yalan
Var biraz da sen oyalan...
WWW
Cevapla
#6
Güzel basit açıklayıcı Smile
Cevapla

Konuyu Paylaş : facebook gplus twitter





Konuyu Okuyanlar: 1 Ziyaretçi