Tam Sürümünü Görmek İçin : Burada delete[] gerekiyor mu?
acehreli
21/11/2004, 03:15
Bir arkadas soyle bir soru sormus:
-------------------------------------------
Pointerlarla ilgili benim bir sorum olacak.
MyClass** pp = new MyClass*[3];
pp[0] = new MyClass[10];
pp[1] = new MyClass[10];
pp[2] = new MyClass[10];
//... do some work...
/* ..Bu kod parçasına na gerek varmı?
for (int i=0;i<3;i++)
{
delete[] pp[i];
}
..end of kod parçası */
// yoksa sadece delete[] pp yaptığımızda bu herşeyi
// halledermi?
delete[] pp;
----------------------------
Yalnizca o satir yetmez. Dongu icindeki delete[]'lere de gerek var. Kisaca kural su: Eger bir bellek new ile ayrilmissa, delete ile geri verilmelidir. Ayni sekilde new[] icin delete[], malloc icin free, vs.
pp[i]'nin gosterdigi bellek new[] ile ayrildigina gore, delete[] ile geri verilmesi gerekir.
Aslinda en iyisi, bu isin akilli gostergelere birakilmasidir. Ama o ayri bir konu... Su iki yazinin yararli olacagini dusunuyorum:
http://www.ceviz.net/index.php?case=article&id=263&catid=13
http://www.ceviz.net/index.php?case=article&id=273&catid=13
Ali
shark_hack
21/11/2004, 17:54
evet delete ile teker teker silmelisin yani oraya delete gerekiyor..... yani pnin i.kaydını bir döngü ile erişip silmen gerekiyor ama şu sorunda var her kaydını ayrı ayrı değilde gözterici kullanmazsan en son kaydın siline bileceği olnağıda var....
acehreli
21/11/2004, 19:24
shark_hack, yanitin icin tesekkurler. Mektubunu bir kere daha okuyup takildigin yerleri noktalama isaretleri koyarak duzeltir misin... Bas tarafini anladim ama son tarafinda ne yaparsam yapayim bir anlam cikartamadim.
Tesekkurler,
Ali
Bence de ayri ayri delete[] gerekiyor.
Bunu dusununca aklima soyle bir soru geldi... Acaba STL deki depolayicilarla bu tur bisey yapsak yine ayni kural mi gecerli olur ?
Mesela std::vector<...> icin... Her elemani, vectora isaret eden isaretci olan bir vector...
std::vector<x> xVec;
std::vector<x> *p = new std::vector<x>();
std::vector<std::vector<x>*> mainCont;
mainCont.reserve(10);
for(int i_=0;i_<10;++i_)
{
// *p ile birseyler yap,birseyler ata...
mainCont.push_back(p);
}
not : sn. Ali Cehreli, bu tur yapilarla calisirken, bol bol typedefleri kullanmamin yararli olacagi ile ilgili tavsiyeleriniz hala kulagimda,unutmadim :) sadece ornek kod oldugundan...
Bu şekildeki bir yapiyla ayrilan bellek nasil geri verilecek ?
mainCont un her bir elemanini icin,o elemana ait vector bozucu islevi mi cagrilmali, yoksa mainCont icin bir tane cagirmamiz yeterli mi ?
Bildigim kadariyla std::vector<...> yazilirken,akilli gostergelerden de yararlanilmis.Buna gore 'sadece mainCont icin kullanirsak yeterli olur' diye dusunuyorum ama emin degilim.
acehreli
23/11/2004, 01:51
ceeyt, kural yine ayni: new ile alinan her bellek delete ile geri verilmelidir. (Ayni sekilde: new[] icin delete[], malloc icin free, fopen icin fclose, vs.)
Eger mainCont'un icindeki her bir nesne new ile ayrilan bellekte oturuyorsa, onlari delete ile geri vermek gerekir. Buyuk olasilikla yine bir dongu yazip ayri ayri delete cagrilacak...
Hayir, vector'un bozucu islevini biz cagirmayacagiz. O islevi delete, sorumlusu oldugu iki isi yaparken cagirir:
1) Bozucu islevi cagirir
2) Bellegi geri verir
vector akilli gostergeler kullanmaz. vector yalnizca kendi ayirdigi bellegi geri verir. Bizim ayirdigimiz bellegi kendi kafasina gore geri veremez, cunku ona gostergelerini verdigimiz nesnelerin hAlA baska bir yerde kullanilip kullanilmadiklarini bilemez.
Eger istersek biz akilli gosterge iceren vector kullanir ve bellegi acikca geri vermekten kurtuluruz:
// AkilliGosterge diye bir sinif oldugunu varsayalim
typedef AkilliGosterge<x> xGostergesi;
typedef vector<xGostergesi> xToplulugu;
xToplugugu xler;
for ( /* ... */)
{
xler.push_back(AkilliGosterge(new x()));
}
Bu kod icin artik delete cagirmaya gerek yoktur. Cunku new ile ayirdigimiz bellegi AkilliGosterge'ye emanet etmisizdir. vector, gerektigi zaman AkilliGosterge'lerin bozucularini cagirir ve bellek AkilliGosterge'lerin bozuculari tarafindan geri verilir. Cunku bir AkilliGosterge'nin bozucusu normalde yalnizca tek bir delete icerir:
AkilliGosterge::~AkilliGosterge()
{
delete p_;
}
Standart kutuphanede bu ise uygun bir akilli gosterge olmadigi icin boost.org'daki Boost kutuphanesindeki akilli gostergeler kullanilir.
Ali
shark_hack
23/11/2004, 18:50
ama buda var eğer vewrileri stacklar sayesinde bir yerde depolarsanız pointer(gösterici)ler sayesinde bunları tekbir delete ile silebilirsiniz.. yada bu stack ı bir snıf olarak kullanıp silme işlşemi gerektiğinde bu stackı akıllı sınıflar kullanarak delegate edebilirsiniz..
ör:
class stack(){}
class aSinif()::~stack(){}
gibi şeklinde düşünürsek yani sınıfı yıkıcı sınıfla yıkarak o andaki etkinliğini kaldırabiliriz...
acehreli
24/11/2004, 09:40
shark_hack, kusura bakma ama soyledigini hic anlamadim. Verdigin ornegi soylediklerinle bagdastiramiyorum. Orada aSinif yerine stack mi yazmak istedin acaba? Eger oyleyse, verdigin kodda bos kapsamlardan baska bir sey goremiyorum. Biraz acar misin lutfen.
Tesekkurler,
Ali
shark_hack
25/11/2004, 14:34
ben sana stack sınıfı oluşturmanı ve o sınıfı daha sonra istediğin yerde devre dışı bırakmanı söylüyorum şimdi daha açıklayıcı oldu sanırım ha o sadece bir açıklama içindi bir örnek kod değildi yani ~class isimi ile sadece devredışı yapacağını göstermiştim okadar yinede biraz kod istiyorsan mailini ver bişiyler yollarım....
acehreli
25/11/2004, 23:58
shark_hack, mektuplarini noktalama isaretleri kullanmadigin ve alisik olmadigim bazi terimler kullandigin icin anlamamisim herhalde.
Noktalama isaretleri kullanmazsan, anlamak cok guclesiyor. Ornegin son yazdiklarina baktigimda sunlardan hangisini soylemek istedigini anlamak ve dogrusunu tahmin etmek zaman aliyor:
1) "... birakmani soyluyorum simdi. Daha aciklayici oldu. ..."
2) "... birakmani soyluyorum. Simdi daha aciklayici oldu. ..."
Hatta yanilmiyorsam onlardan sonra gelen "sanirim" da ikinci cumleye ait olacak. Noktalama isaretleri gercekten yararlidir. Kendi yazdigin mektuplari bir iki hafta sonra tekrar okudugunda ayni sorunlari sen de yasayacaksindir.
Simdi anladigim kadariyla, bir topluluk yazmamizi ve o topluluk icine koyacagimiz nesneleri yerlestirme new'u (placement new) ile kurmamizi, ve bozucu islevleriyle de bozmamizi soyluyorsun. Ondan sonra da yalnizca tek bir free ile bellegi tumden geri verebiliriz. Iyi bir fikir... std::vector de oyle yapar zaten.
Boyle bir durumda delete[] degil free kullanmak daha iyi olur, cunku malloc ile ayirdigimiz bellegi bir nesne olarak degil, siradan bir bellek parcasi olarak kullaniyoruz.
Sanirim suradaki gibi bir kullanimdan bahsediyorsun:
#include <iostream>
using std::cout;
class Sinif
{
Sinif(Sinif const &);
Sinif & operator= (Sinif const &);
public:
Sinif()
{
cout << "kuruldu\n";
}
~Sinif()
{
cout << "bozuldu\n";
}
};
#include <stdlib.h>
int main()
{
// Depolama bellegini ayir
char * bellek = (char *)calloc(1, sizeof(Sinif));
// Acikca kur
Sinif * nesne = new (bellek) Sinif();
// Nesneyi kullanan kod buraya gelecek...
// Acikca boz
nesne->~Sinif();
// Depolama bellegini geri ver
free(bellek);
}
Eger dogru anladiysam, bu toplulugun bir yigit (stack) da olmamasi gerekir, cunku yukarida verilen kod daha cok bir matris olusturmaya calisiyor gibi gorunuyor. (Bu arada, soruyu benim sormadigim acik degil mi? En basa "Bir arkadas soyle bir soru sormus" yazmistim...)
Yine eger dogru anladiysam, boyle bir toplulugu kendimiz yazmak yerine tabii ki oncelikle standart kutuphanedeki topluluklardan yararlanmayi dusunmeliyiz.
Ayrica, ozel mektupla kod gondermeyin lutfen. Konu burada acildi, burada devam etsin. Yoksa hem gonderilen kodun yararli taraflarini diger forum uyelerinden esirgemis oluruz, hem de o uyelerin koddaki olasi yanlisliklar uzerine yapacaklari olumlu elestirileri engellemis oluruz.
Ali
shark_hack
27/11/2004, 17:10
evet benim söylediğim de senin yazdığına benzer birşeydi. söylediklerimi anlamışsın.. kusura bakma biraz fazla bilgisayar başında olduğum için hızlı hızlı cevap yazıyorum. ve noktalama işaretlerine önem vermiyorum.. bu biraz zorluk sağlar. ama tamammen cevabı okursan anlamakta güçlük çekmezsin....:-)
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.