[linux-programlama] Re: c pointer sorunu

---------

From: Serdar KÖYLÜ (serdarkoylu@fisek.com.tr)
Date: Thu 07 Aug 2003 - 21:43:43 EEST

  • Next message: Halil Demirezen: "[linux-programlama] Re: c pointer sorunu"

    Selamlar..

    On Thu, 7 Aug 2003 21:25:58 +0300
    Halil Demirezen <halild@bilmuh.ege.edu.tr> wrote:

    >
    > evet burada serdar arkadasimizi dogrulayacak bir kode ornegi var.
    > Mesela s degiskeni bir char pointer mevcut 32 bit linuxlarda 4 byte
    > bir adress. sonra gidip malloc ile 10 byte yada 10 karakterlik bir
    > array olusturup pointer e bu arrayin adresini ariyoruz. Ve o pointer
    > uzerinden o adrese

    Biraz farkli bir is aslinda yaptiginiz.

    > s = (char *)malloc(10);

    s, 10 Bayt uzunlukta bir buffer (arabellek) i gosteriyor artik. Bufferin
    icinde ne var belirsiz.

    > s = "deneme";

    > "deneme" stringini atiyoruz. Hicbir Segmentation fault alamiyorsunuz.

    Hayir, s pointerinin degerine text segmentindeki "deneme" sabitinin
    bulundugu adresi yazdiniz bununla. Zaten segfault vs. alacak bir sey
    yok. Yazilan deger auto-alloc edilmis olan s pointerinin oldugu bellek
    hanesi.

    Bir onceki islemle bunun arasinda hic bir baglanti yok. s'nin icerigi
    uzerine yazildigi icin kayboldu. Onceki 10 Baytlik bufferiniz artik
    "garbage". Yada bir diger deyisle "Memory Leak".. Programiniz sona
    erinceye kadar hafizada yer isgal edecek. Su durumda free etme sansinz
    yok :))

    > Ama literaller benim de tereddut ettigim gibi read only text
    > segmentinde saklaniyor. Boylece herhangi bir yazma isleminde
    > Segmentation Fault aliyorsunuz.

    Konuyu daha iyi anlamak iicn soyle bir harita dusunelim.

    0 - 100 Stack olsun.
    500 - 1000 Data bolgesi (data rw-)
    2000 - 4000 Kod bolgesi (text r-x)

    Simdi fonksiyona girince

    100 - s -> Icerigi belirsiz.
    99 - return icin geri donus adresi.

    s = malloc(10);

    100 - s -> icerigi malloc'un dondurdugu deger olur.
    . Diyelim ki malloc geriye 500 adresini dondurdu.
    . bu durumda s'nin icindeki deger 500'dur. Bu, *s yazdiginizda
    . kullanilacak degerdir.

    *s = 1;

    s = 500 olduguna gore, 500. Bellek noktasina 1 konacaktir.

    Diyelimki, sabitimiz 2400. Adreste olsun.

    2400 - 'A'
    2401 - 'B'
    2402 - 'C'
    2403 - '\0'

    Seklinde olur. Simdi

    s = "ABC"

    dedigimizde bu kez, 100. Baytta (stacktaki s degeri) bulunan
    s'nin icerigi 2400 olur.

    Simdi kabaca bakarsak:

    0...98 - Belirsiz (STACK, burada bizi cagiran fonksiyonun degiskenleri
    vs. var.)
    99 - Geri donus adresi.
    100 - s
    101...499 - Belirsiz
    500 - 509 - malloc ile ayrilmis bolge. Icerigi mechul.
    510 - 2399 - Belirsiz veri ve komutlar..
    2400 - 'A'
    2401 - 'B'
    2402 - 'C'
    2403 - '\0'
    2404 - .... Belirsiz..

    Goruldugu uzere yeni bellek duzenimiz bu sekilde. Bu son derece
    basitlestirilmis bir yapi. Dahasi sadelestirme adina bazi birazcik
    hatali. Ama bellekte bu dumenin nasil dondugunu biraz ozetleyebilir.

    Pointerin calisma prensibini anlamak icin bir super isaretci dusunun. Bu
    isaretci nereyi gosteriyorsa CPU bellegin orasina yazacak veya okuyacak.
    Eger,

    ptr = 100

    derseniz, bu super isaretciye ptr'nin adresi yazilir.

    *ptr = 100

    derseniz, super isaretci once ptr'nin oldugu adresi gosterir. ptr'nin
    icindeki deger okunur ve o deger super isaretciye yazilir. Devaminda 100
    sayisida bu isaretcinin gosterdigi yere yazilir. Boyle olunca
    pointerlerin her zaman mutlak adresi gosterebilme yetenegi olur. Ama bir
    array stack uzerinde calisir, heap (data segmenti) uzerinde bulunmaz.
    Cogu derleyici icin bu gecerlidir. Ornegin "char arr[3]" belirtimi,
    bizim stack'imizin soyle olmasina yol acar:

    char arr[3];
    char *ptr;

    arr[0] = 'X';

    Satirlari icin baslangicta:

    100 -> ptr
    99 - arr[3]
    98 - arr[2]
    97 - arr[1]
    96 - arr[0]
    95 - return icin geri donus adresi.

    veya derleyicinin yogurt yemesine gore:

    100 - arr[3]
    99 - arr[2]
    98 - arr[1]
    97 - arr[0]
    96 -> ptr
    95 - return icin geri donus adresi.

    Simdi super isaretcimiz SI olsun..

    arr[n] = 'X'; komutu

    SI = 97
    SI = SI + n
    'X' degerini yaz..

    Seklinde olur. Eger

    ptr = arr;

    yazarsak;

    SI = 96
    97 degerini yaz..

    Seklinde olur. Simdi

    ptr[n] = 0;

    SI = 96
    oku
    SI = okudugun deger.
    SI = SI + n
    0 degerini yaz..

    Seklinde cevrilebilir. Dikkat ederseniz, bir array dogrudan bellegi
    isaret ediyor. Bu yuzden r/w olmak durumunda. Ama bir pointer oyle olmak
    zorunda degil.. Onun icinde her zaman SI dedigimiz CPU'nun nereye
    yazacagini gosteren bir baska adres bulunuyor..

    Simdi ne anlasiliyor ? Sanirim biraz daha aciklayici olmustur...

    Saygi ve sevgiler..


  • Next message: Halil Demirezen: "[linux-programlama] Re: c pointer sorunu"

    ---------

    Bu arsiv hypermail 2.1.6 tarafindan uretilmistir.