Foo* set = new Foo[100];
// ...
delete [] set;
Dizinin sınırlarını geçemezsiniz delete[]
. Peki bu bilgiler nerede saklanıyor? Standart mı?
Foo* set = new Foo[100];
// ...
delete [] set;
Dizinin sınırlarını geçemezsiniz delete[]
. Peki bu bilgiler nerede saklanıyor? Standart mı?
Yanıtlar:
Öbek üzerinde bellek ayırdığınızda, ayırıcısı ne kadar bellek ayırdığınızı takip edecektir. Bu genellikle tahsis ettiğiniz hafızadan hemen önce bir "baş" segmentinde saklanır. Bu şekilde, hafızayı boşaltmanın zamanı geldiğinde, ayrıştırıcı ne kadar hafızanın boşaltılacağını tam olarak bilir.
free
kadar bellek ayırılacağını nasıl bilir". Evet, bellek bloğu boyutu " malloc
normalde bloğun kendisinde " tarafından bir yerde saklanır , bu yüzden böyle free
bilir. Ancak, new[]
/ delete[]
farklı bir hikaye. İkincisi temelde malloc
/ üstünde çalışır free
. new[]
ayrıca oluşturduğu öğe sayısını bellek bloğunda (bağımsız olarak malloc
) saklar , böylece daha sonra delete[]
bu numarayı alıp uygun sayıda yıkıcıyı çağırmak için kullanabilir.
malloc
) ve eleman sayısı (by new[]
). Birincisinin ikincisini hesaplamak için kullanılamayacağını unutmayın, çünkü genel olarak bellek bloğunun boyutu istenen boyut dizisi için gerçekten gerekenden daha büyük olabilir. Ayrıca dizi öğesi sayacının yalnızca önemsiz yıkıcıya sahip türler için gerekli olduğunu unutmayın. Önemsiz yıkıcıya sahip tipler için sayaç, new[]
elbette tarafından alınmaz ve alınmaz delete[]
.
Derleyicilere yönelik yaklaşımlardan biri, biraz daha fazla bellek ayırmak ve bir kafa elemanında bir dizi elemanı saklamaktır.
Nasıl yapılacağına örnek:
Buraya
int* i = new int[4];
derleyici sizeof(int)*5
bayt ayırır.
int *temp = malloc(sizeof(int)*5)
İlk sizeof(int)
baytta "4" depolayacak
*temp = 4;
ve ayarla i
i = temp + 1;
Yani i
5 değil 4 elemanlık bir diziyi gösterecektir.
Ve silme
delete[] i;
aşağıdaki şekilde işlenecektir:
int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed
free (temp)
Bilgiler standartlaştırılmamıştır. Ancak bu bilgiler üzerinde çalıştığım platformlarda ilk öğeden hemen önce bellekte saklanıyor. Bu nedenle teorik olarak ona erişebilir ve inceleyebilirsiniz, ancak buna değmez.
Ayrıca bu yüzden delete [] ile bellek ayırdığınızda delete [] kullanmalısınız, çünkü delete dizisi sürümü doğru miktarda belleği boşaltmanın ve uygun sayıda yıkıcı çağırmanın gerekli olduğunu (ve nerede) bildiğinden nesneler için.
Temel olarak bellekte düzenlenmiştir:
[info] [mem istediğiniz ...]
Bilgi, derleyiciniz tarafından ayrılan bellek miktarını depolamak için kullanılan yapıdır ve ne değildir.
Ancak bu uygulamaya bağlıdır.
C ++ standardında derleyiciye özgü olarak tanımlanmıştır. Bu da derleyici büyüsü demek. En az bir büyük platformda önemsiz hizalama kısıtlamaları ile kırılabilir.
delete[]
Yalnızca döndürülen işaretçiler için tanımlanmış olan ve döndürülen işaretçi new[]
olmayabilir, olası uygulamaları düşünebilirsiniz operator new[]
. Vahşi bir uygulama tarafından döndürülen ilk int dizi sayısını saklamaktır operator new[]
ve sahip new[]
olduğu geçmiş ofset bir işaretçi döndürür. (Bu yüzden önemsiz olmayan hizalamalar kırılabilir new[]
.)
Unutmayın operator new[]/operator delete[]
! = new[]/delete[]
.
Ayrıca, bu, C'nin ayrılan belleğin boyutunu nasıl bildiği ile dikeydir malloc
.
Çünkü 'silinecek' dizi, 'yeni' operatörün tek bir kullanımı ile oluşturulmalıdır. 'Yeni' işlemin bu bilgiyi yığına koyması gerekirdi. Aksi takdirde, yeni ek kullanımların yığının nerede bittiğini nasıl bilebilir?
Standart değildir. Microsoft çalışma zamanında yeni işleç malloc () kullanır ve delete operatörü free () kullanır. Bu durumda, sorunuz aşağıdakine eşdeğerdir: free () bloğun boyutunu nasıl bilir?
Sahne arkasında, yani C çalışma zamanında, bazı defter tutma vardır.
Bu, ilk başta düşündüğünüzden daha ilginç bir sorundur. Bu cevap olası bir uygulama ile ilgilidir.
İlk olarak, bir düzeyde sisteminizin bellek bloğunu nasıl 'boşaltacağını' bilmek zorunda kalırken, temel malloc / free (hangi yeni / delete / new [] / delete [] genellikle çağırır) her zaman tam olarak ne kadar bellek hatırlayacağını hatırlamaz isteyebilirsiniz, yuvarlanabilir (örneğin, 4K'nın üzerinde olduğunuzda, genellikle bir sonraki 4K boyutlu bloğa yuvarlanır).
Bu nedenle, bellek bloğunun boyutunu alabilseniz bile, bu yeni [] ed bellekte daha küçük olabileceği için kaç değer olduğunu bize söylemez. Bu nedenle, bize kaç değer olduğunu söyleyen ekstra bir tamsayı depolamamız gerekir.
DIŞINDA, inşa edilen tipin bir yıkıcı yoksa, o zaman silme [], bellek bloğunu boşaltmak dışında bir şey yapmak zorunda değildir ve bu nedenle hiçbir şey depolamak zorunda değildir!