PDA

Tam Sürümünü Görmek İçin : realloc(p,0) yasal mı?


ceeyt
02/03/2005, 01:02
Bugun aklima 'realloc( )' fonksiyonunun 2. degiskeni olarak 0 sayisinin kullanilip kullanilamadigi ve eger kullanilabiliyorsa 'free( )' gibi calisip calisamayacagi takildi.

Eve gelir gelmez denedim, 'free( )' gibi calisti ( veya bana oyle geliyor :) ).

yani ;
free(p); yerine realloc(p,0);
Acaba bu kullanim yasal midir ?
Yoksa uykusuz gecelere uzanan bir hataya mi yol acar ? :)


acehreli
02/03/2005, 01:53
realloc, Herb Sutter ve Andrei Alexandrescu'nun C++ Coding Standards kitaplarinin besinci maddesinde kotu tasarim ornegi olarak gecer:

<ceviri>
realloc standart C'de UnlU bir kotu tasarim ornegidir. Cok fazla sey yapmak zorundadir: NULL gonderilirse bellek ayir, buyukluk olarak 0 gonderildiginde bellegi geri ver, eger olabiliyorsa nesnelerin yerini degistirmeden tekrar ayir, eger olamiyorsa nesneleri baska bir yere tasi. Kolayca genisletilemez. Ileriyi gormeden yapilmis kotu bir tasarim olarak kabul edilir.
</ceviri>

Ali

ceeyt
02/03/2005, 02:05
NULL gonderilirse bellek ayir,


yani sadece free( ) degil malloc( ) yerine de realloc( ) kullanilabiliyor ve yasal. Daha dogru bir ifadeyle tasarimi boyle ve yanlis oldugu dusunuluyor.


eger olamiyorsa nesneleri baska bir yere tasi.


Bu realloc( ) islevinin, eger gerekli sartlar gerceklesirse bellek blogumuzu istedigi yere tasiyabilecegi anlamina mi geliyor ?

acehreli
02/03/2005, 03:03
Evet, malloc'luk da yapar ve evet, blogu baska yere de tasir (yeni yerin adresini dOndUrUr).

realloc'un neden kotu tasarlandiginin dusunuldugunu yazmayi unutmusum. O maddenin basligi, "Bir seye tek bir tutarli ve kullanisli gorev verin." realloc'un tanimi cok karisiktir.

Bu arada, ayni maddedeki ikinci ornek de std::string'dir :) Onun da arayuzu cok buyuktur. Bir anlamda fazla is ustlenmistir.

Ali

PUNK
10/04/2005, 16:01
konuyla fazla alakası olmayan ama gende alakalı bi soru soracam
programımda w1 diye bir diz var var var kullanıcı bişeyler yapıp cs değerini artırdıkça w1 için yer açıyorum
başlangıcta aşağıdaki kod işliyor
W1=(int*)malloc(4);

cs nin her artırımında kontroldeki belleği buyutuyorum
W1=(int*)realloc(W1,4*cs);
şimdi sizin anlatıığınıza gore bu kotu bir tasarımmı
öyleyse iisi nasıl vede malloc realloc fonk. ile iki boyutlu dizi için nasıl yer ayrılıyor teşşekur ederim kolay gelsin herkese

acehreli
11/04/2005, 19:21
Aktardigim yazida soylenmek istenen, islevlere kucuk gorevler verilmesinin onemli olduguydu. Bir islevin isleyisini "eger su olursa sunu yapar, ama eger soyleyse soyle olur, ve hatta soyle bir durumda da soyle yapar" gibi anlatabiliyorsak, o islevde bir sorun var demektir. Yazida soylenen bu...

Ama senin durumunda realloc tam da istedigin gibi calisiyor iste. Senin kullaniminda temelde bir sorun yok, ama aklima iki nokta geliyor:

1) Kapasiteyi birer birer buyutursen, cs==N oldugu durumda N kere bellek ayirmis olursun; ama bunun sonucunda (N-1)*(N-2) kere veri tasinmis olabilir.

1 + 2 + ... + N-1 = (N-1) * (N-2) = N*N - 3N + 2

N==1000 oldugunda 999 kere bellek ayrilacak ve 997002 kere int aktarilacaktir...

[Not: Aslinda 997002 kere int aktarma isi tek tek yapilmayacaktir tabii ki. Islemci hizli bir sekilde 999 kere "bellek kopyalama" isi yapacaktir.]

Eger her seferinde kapasiteyi gereginden fazla olarak buyutursen, yani bir anlamda "eger kapasite yetmediyse, bir tane arttirmak yine yetmeyecektir" diye dusunursen; cs'in asagidaki degerleri icin kapasiteyi soyle ayirirsan:


cs kapasite aktarma sayisi
-------------------------------
1 1 0 (baslangic)
2 2 1
3 4 3
(cs==4 oldugunda yer ayirmaya gerek yok; cs==3 iken ayirmistik)
5 8 7
9 16 15
17 32 31
33 64 63
65 128 127
129 256 255
257 512 511
513 1024 1023


Yani toplam 10 kere yer ayirmak yetti... Kopyalanan 'int' sayisi da bu durumda cok daha kucuk oldu: Sanki her zaman icin 2*N'den daha kucuk oluyormus gibi degil mi... std::vector gibi topluluklar da kapasitelerini boyle arttirdiklari icin, aslinda burada karmasiklik O(N) galiba... (Fazladan harcanan zaman "amortize" olur ve N buyudukce, oge basina fazladan harcanan zaman sifira dogru gider ve O(N)'i buluruz. (Galiba... (?)))

Tabii bu hesaplar int gibi temel turler icin cok onemli olmayabilir; cunku o turun oturdugu buyuk bir bellek bolgesi, islemcinin ve bellek mimarisinin yardimiyla cok hizlica bir seferde kopyalanabilir. Asagidaki maddede oldugu gibi, her bir oge icin bir islev cagrilmasi gereken durumlarda ise kazanc cok onemlidir.

[Not: Yukaridaki tablo kapasiteyi her seferinde %100 arttiriyor. O yuzde cok kullaniliyor olsa da, %50 arttirmanin daha iyi oldugu gosterilmistir. Yani aslinda kapasite 1, 2, 3, 5, 8, 12, ... gibi artmalidir. (Hatta en dogrusu, kapasiteyi Fibonacci serisindeki degerler gibi arttirmaktir... :)]

2) realloc'u kopyalayicisi olan C++ siniflariyla kullanamazsin, cunku kopyalayici islev nesnenin tutarliligini saglamak icin onemli isler yapiyor olabilir. Ornegin bir oge baska bir ogenin adresini gosteriyor olabilir ( p = &i; ). Nesne bir yere kopyalaninca, bu p==&i sarti kaybolmus olur.

Ali