Forum: D Programlama Dili RSS
Dizi sınırı ayarlanabiliyor mu?
Overflow for static array!
Page:  1  2  next 
Avatar
Salih Dinçer #1
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Subject: Dizi sınırı ayarlanabiliyor mu?
Merhaba,

Sınırdan kastım derleyicinin kısıtlması, derleme anında ise şu hatayı almaktayım:
bws.d(13): Error: index 16777216 overflow for static array
Acaba bir derleme parametresi mi var? Çünkü bu değer, en fazla (2^24)-1 olması gerektiğine işaret ediyor. Dizi 1 byte'lık (ubyte) verilerinde oluşuyor. Aslında aynı hatayı D1 derleyicisinde alınca D2'yi denemeyi düşündüm. Son sürümde, olası en fazla dizi elemanı sayısının daha fazla olacağını zannetmiştim.

Bunu arttırmanın bir yolu var mı? Eğer yoksa dinamik dizi kullanımını nasıl yapabilirim? Aslında başlangıçtaki değerlere ihtiyaç duymuyorum ve baştakileri silip yoluma devam edebilirim. Şimdi sitemizde bellek makalesini buldum; araştırmadayım:

[Image: http://ddili.org/forum/unb_lib/designs/modern/img/arrow_right.png]Bellek Yönetimi (Memory Management) - Çeviren: Ali Çehreli (14 Temmuz 2009)

Sevgiler, saygılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
This post was edited on 2012-01-29, 09:30 by Salih Dinçer.
acehreli (Moderator) #2
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
Program yığıtının büyüklüğü işletim sisteminin bir sınırıdır. Onunla mı ilgili acaba? Yoksa dilde böyle bir kısıtlama bilmiyorum.

Programcı hatası da olabilir. (Ben hep yapıyorum. ;)) Denediğin kodu gösterir misin.

Ali
acehreli (Moderator) #3
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
In reply to post #1
Quote by Salih Dinçer:
bellek makalesini buldum; araştırmadayım

Bence hiç başlama! :) D1 zamanından kalma bir makale o. Artık byte diye bir tür bile kalmadı.

Ali
acehreli (Moderator) #4
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
Fikrimi değiştirdim: Makale yine de yararlı tabii ama D1 zamanında yazıldığını unutmamak gerek.

Ali
Avatar
Salih Dinçer #5
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Yazılımın kurulum bölümü şöyle:
import std.stdio, std.cstream;
 
    const short xVagon = 8;       
    const uint xAsal = 268435439; //179424673;
    const uint xDizi = (xAsal/16) + 1; //16777216
 
    struct Tren {
            uint bayt;
            ubyte bit;
    };
 
    Tren[xVagon] vagon;
    ubyte[xDizi] xData;
Aynı hatayı 64 bit bir sistemde ve 8 GB. bellekte de aldım. Bu arada makaleyi okumaya başladım da hoşuma gitti...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
This post was edited on 2012-01-29, 09:45 by Salih Dinçer.
Avatar
Salih Dinçer #6
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Bu kodu şimdi tekrar denedim ama ubyte veri tipini uint ile değiştirdim. Sanırım her bir eleman bellekte 32 bit yer kapladığından yine sorun oldu. Hata iletisindeki sayısal değerin bir eksiğinde taşma olduğunu belirtti; bu (2^24)-1 demekti. Bu durumda 32 bit değişkenler için 2^22 ile 4'e bölmem gerekir.
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderator) #7
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
D'de sabit uzunluklu dizi (statik dizi) ve dilim farklı. Sabit uzunluklu diziler değer türleri oldukları için oldukları gibi program yığıtında oturmak zorundalar. İşletim sisteminin bir duvarına çarpmış oluyoruz.

Çözüm olarak bütün dizi dinamik olarak new ile ayrılabilir. Onu da dilim olarak kullanabiliriz:

    ubyte[] xData = new ubyte[xDizi];

Ali
Avatar
Salih Dinçer #8
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Bu şekilde iki sürümde de denedim hata alıyorum:
salih@DB-N150-N210-N220:~$ dmd bws.d
bws.d(15): Error: cannot evaluate new ubyte[](161u) at compile time
salih@DB-N150-N210-N220:~$ gdc bws.d -o bws
bws.d:15: Error: non-constant expression new ubyte[](cast(uint)161)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderator) #9
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
Kodda o satırı görebilir miyiz? Ben başına enum yazınca aynı hatayı alıyorum:

    enum xData = /* ... */;

Bazı işlemler henüz derleme zamanında yapılamıyorlar. Bunların sayısı gittikçe azalıyor.

Ali
Avatar
Salih Dinçer #10
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Kusura bakmayın, hata bendeymiş. Gerekli, gereksiz o kadar çok şey deniyorum ki diziyi new ile sınıf (class mat) içinde tanımlamışım. İşte deneme kodum şöyle ve denediklerimin sadece küçük bir kısmı...:)
class mat {
    const int on = 10;
    static uint yedi = 7;
    static ubyte[] veri;
 
    static int karesi(int i) { return i * i; }
}
void main () {
    auto d = new mat[100];
    //ubyte[8379984] veri;
    d[1].veri = new ubyte[16777214*mat.on];
    d[2].veri = new ubyte[16777214*20];
    writefln ("%d", d[1].veri.length);
                    d[1].veri[335544280-1] = 1;
    writefln ("%d", d[2].veri[335544280-1]);
/*    
    writefln("d'nin karesi:\t%d", d[0].karesi(d[0].yedi));
    writefln("d'nin yedisi:\t%d", d[0].yedi);
    d[0].yedi = 8;
    writefln("d'nin yedisi:\t%d", d[0].yedi);
    writefln("d'nin karesi:\t%d", d[0].karesi(d[0].yedi));//*/
    din.readLine();
}
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
This post was edited on 2012-01-30, 03:50 by Salih Dinçer.
Avatar
Salih Dinçer #11
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Düzeliyorum...:)

Şu şekilde istediğim değeri sınıf içinde de verebildim! Yahu ben D'yi çok sevdim:
import std.stdio, std.cstream, std.md5;
class bellek {
    const int on = 10;
    static uint yedi = 7;
    static ubyte[] veri;
    
    this(int i=on) {
        veri = new ubyte[i*yedi];
    }
}
void main () {
    auto d = new bellek(16777214);
 
    //writef ("%d ", d.veri.length);/*
    writefln ("[%s]", getDigestString(d.veri));//*/
}
Henüz D'nin dünyasına girmemiş olanlar için ekrana yazılan iki satırın görüntüsü de şu şekildedir:
salih@DB-N150-N210-N220:~$ ./bel
117440498 [4CE33F8646C98240603D723E9FEE3FA6]
(d'yi bellek sınıfına varsayılan değerleriyle tanımlayınca da aşağıdaki gibi bir sonuç alıyorsunuz...)
70 [3287282FA1A1523A294FB018E3679872]
Ne diyelim C'ye kapak olsun, maşaallah...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
This post was edited 3 times, last on 2012-01-30, 05:50 by Salih Dinçer.
acehreli (Moderator) #12
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
D'de bütün değişkenler ilklenirler (her tür kendi .init değeriyle):

class C
{
    int i;
 
    this()
    {
        assert(i == i.init);     // <-- zaten 0 ile ilklenmiş
    }
}

Yukarıda this()'e girildiğinde i zaten int.init ile ilklenmiştir (i.init ile int.init aynı ve çoğu tür için 0). Ama eğer i'nin 10 gibi özel bir değer olması gerekiyorsa onun önceden 0 ile ilklenmesi saçma olur. Üye tanımında bizim belirlediğimi ilk değer, derleyicinin ilkleme adımını ortadan kaldırır:

class C
{
    int i = 10;
 
    this()
    {
        assert(i == 10);         // <-- özel değerle ilklenmiş
    }
}

Üye tanımındaki değerlerin derleme zamanında bilinmeleri gerekiyor. Ama D'nin derleme zamanında kod işletebiliyor olması çok yararlı:

import std.exception;
 
string foo()
{
    return "merhaba";
}
 
string bar()
{
    return "dünya";
}
 
string selam()
{
    return foo() ~ ' ' ~ bar();
}
 
class C
{
    int i = selam().length;       // <-- derleme zamanında işletilir
}
 
void main()
{
    auto c = new C;
}

Tabii onun için bütün işlevlerin gerçekten de derleme zamanında işletilebiliyor olmaları gerekir. Örneğin girişten bilgi alınamaz! :-p (Başka kısıtlamalar da var.)

Ali
Avatar
Salih Dinçer #13
Member since Jan 2012 · 411 posts · Location: İstanbul
Group memberships: Üyeler
Show profile · Link to this post
Çok teşekkürler, bunlar değerli bilgiler. Tabi tüm değişkenler derleme zamanı birbirine oturduğundan (-bknz. aşağıdaki örnek) teorik olarak bir esprisi yok gibi. Ama duruma göre faydaları tartışmasız!
...
d[1].veri = new ubyte[16777214*mat.on];
d[2].veri = new ubyte[mat.karesi(mat.yedi)]; //<--- bunun yerine ubyte[49] veri; yazmak yeterli, komik değil mi...:)
...
Bu örneği iki önceki iletimde vermiştim. İkinci satırdaki çok gereksiz dolambaçlı bir değeri oradan alıp dolaştırıyor; yoksa 49 yazmak bile yeterli! Elbette bu bir deneme çünkü mat.veri dizisi static olduğu için 1. ve 2. kopyası aynı.

Peki ya static olmaz ise niye "Parçalama arızası" verir? Örneğin şurada statik olmayan sınıf elemanlarına hiç bir şekilde ulaşamıyorum:
class bellek {
    int d;
    static int s;
}
static void main () {
    auto b = new bellek [2];
    b[1].s=1;
    writefln ("static bellek'in 1. elemanı: %d", b[0].s);
    writefln ("static bellek'in 2. elemanı: %d", b[1].s);
}
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderator) #14
User title: Ali Çehreli
Member since Jun 2009 · 2279 posts
Group memberships: Genel Moderatörler, Üyeler
Show profile · Link to this post
Quote by Salih Dinçer:
Peki ya static olmaz ise niye "Parçalama arızası" verir? Örneğin şurada statik olmayan sınıf elemanlarına hiç bir şekilde ulaşamıyorum:
class bellek {
    int d;
    static int s;
}
void main () {
    auto b = new bellek [2];
    b[1].s=1;
    writefln ("static bellek'in 1. elemanı: %d", b[0].s);
    writefln ("static bellek'in 2. elemanı: %d", b[1].s);
}

Hatırlatmak için, ve başka arkadaşlar denemedilerse diye, static üyeler bütün tür için tek oluyorlar; static olmayan üyeler ise her nesne için ayrı oluyorlar. Yani yukarıdaki bellek.s yalnızca bir adet ama bellek.d her nesne için farklı.

Yukarıdaki programı işlettiğimizde şunu görüyoruz:

static bellek'in 1. elemanı: 1
static bellek'in 2. elemanı: 1


İki elemanın s üyeleri de aynı olduğu için ikisi de aynı. O üyeyi b[1].s diye ilklemek yerine sınıfın 'static this' işlevi de kullanılabilir. 'static this' her tür için yalnızca bir kere işletilir ve en azından o türün static üyelerini ilklemek için mantıklıdır:

class bellek {
    int d;
    static int s;
 
    static this()
    {
        s = 42;
    }
}

Yukarıdaki kod sabit bir değer kullandığı için s aslında tanım satırında da ilklenebilir:

class bellek {
    int d;
    static int s = 42;
}

Ama tabii 'static this' bambaşka kodlar da işletilebildiği için duruma göre yeğlenir.

static olmayan üyeler konusunu sona bıraktım. :) b[0].d deyince hata olmasının nedeni, D'de sınıfların referans türü olmaları. b[0] ve b[1] C'deki NULL göstergelerinin eşdeğeri durumundalar. Gerektiğinde şöyle denetlenebilir:

        if (b[0] is null)

class nesnelerinin new ile oluşturulmaları gerekir. struct'ta durum öyle değil, çünkü onlar değer türleri. C ve C++'tan gelenler (ben dahil! :)) referans türlerine yabancı olabilirler. Java ve C#'tan gelenler zaten biliyor olmalılar. Bununla ilgili şöyle bir şey var:

  http://ddili.org/ders/d/deger_referans.html

Ayrıca bu sorunun dizilerle ilgisi olmadığını da belirtmek gerek, yoksa şu da aynı hataya sahip:

    bellek b;
    writeln(b.d);

Daha da ayrıca, :) main'in başındaki 'static'i hiç görmemiştim. Etkisi olduğunu sanmıyorum.

Son olarak, eğer bütün dizi baştan oluşturulması gerekmiyorsa diziyi hep sonuna ekleyerek de oluşturabilirsin:

import std.stdio;
import std.string;
 
class bellek {
    int d;
    static int s;
 
    this(int d) {
        this.d = d;
    }
 
    override string toString() const
    {
        return format("%s", d);
    }
}
 
void main () {
 
    bellek[] dizi;
 
    foreach (i; 0 .. 10) {
        dizi ~= new bellek(i);
    }
 
    writeln(dizi);
}

Ali
zafer #15
Member since Jul 2009 · 356 posts · Location: Ankara
Group memberships: Üyeler
Show profile · Link to this post
Ali zaten çok güzel bir açıklama eklemiş ancak ben Salih'in kodunu aşağıdaki şekle getirip çalıştırınca sorunsuz çalıştığını gördüm. Tabi bu durumda benimde aklımda bazı sorular oluştu, önce kodu görelim;

import std.stdio;
 
class bellek 
{
    int d;
    static int s;
}
 
void main () 
{
    bellek[3] b = new bellek();
    
    b[0].s = 0; 
    b[0].d = 1;
    
    b[1].s = 2; 
    b[1].d = 3;
    
    b[2].s = 4; 
    b[2].d = 5;
    
    writefln ("static bellek'in 1. elemani: %d", b[0].s);
    writefln ("static bellek'in 2. elemani: %d", b[0].d);
    
    
    writefln ("static bellek'in 1. elemani: %d", b[1].s);
    writefln ("static bellek'in 2. elemani: %d", b[1].d);
    
    
    writefln ("static bellek'in 1. elemani: %d", b[2].s);
    writefln ("static bellek'in 2. elemani: %d", b[2].d);
    
    
    /*
    auto b = new bellek [2];
    b[1].s=1;
 
    writefln ("static bellek'in 1. elemanı: %d", b[0].s);
    writefln ("static bellek'in 2. elemanı: %d", b[1].s);
     */
}

static bellek'in 1. elemani: 4
static bellek'in 2. elemani: 5
static bellek'in 1. elemani: 4
static bellek'in 2. elemani: 5
static bellek'in 1. elemani: 4
static bellek'in 2. elemani: 5

Kod üzerinde de görüleceği üzere önce "b" isimli bir sınıf değişkeni tanımladım ama bu değişkeni bir dizi olarak tanımladım. Bu esnada 3 elemanlı bir dizi tanımlıyorum ama bunlara sadece bir sınıf kurup onu atıyorum. Doğal olarak dizideki tüm elemanlar aynı nesneyi refere ediyor. Zaten bunu aşağıdaki çıktıda görmek mümkün şeklinde bir açıklama getiriyorum, katılır mısınız?

Diğer taraftan sınıfda bulunan "d" üye değişkenine ulaşmayı beklemiyordum ama gördüğünüz üzere değer atayıp okumayı başardım. Bu konuda  asıl bir açıklama yapılabilir?
http://www.zafercelenk.net - site    ||    https://github.com/zafer06 - depo
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please note the verification code from the picture into the text field next to it.
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Page:  1  2  next 
Not logged in. · Lost password · Register
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Current time: 2012-05-18, 10:05:41 (UTC -07:00)