2013-07-15 19 views
5

NSData nesnesine sarmak istediğim büyük bir bölgem var. Bir süre sonra, o NSData nesnesinin bir kopyasını yaparım. İki NSData nesnesinin bağımsız bir yaşam sürmesini istiyorum. ARC, NSData nesnelerini yeniden saymayı önemser, ancak içeren malloc'd bölgesi'un ömrünü açıklığa kavuşturmaya çalışıyorum. İşte bir kod taslak verilmiştir:NSData içeriği ayrı olarak referans sayılıyor mu?

float* cubeData = (float*)malloc(cubeDataSize); 
printf("cubeData=%p\n", cubeData); 
// cubeData=0x01beef00 

for (...) { /* fill the cubeData array */ } 

NSData* data = [NSData dataWithBytesNoCopy:cubeData length:cubeDataSize 
    freeWhenDone:YES]; 

NSData* data2 = [data copyWithZone:nil] 

printf("data.bytes=%p data2.bytes=%p\n", data.bytes, data2.bytes); 
// data.bytes=0x01beef00 data2.bytes=0x01beef00 

Benim için sorun malloc'd bölgeyi derin kopya etmediğini copyWithZone - Derin kopyasını istiyorsanız ben [NSData dataWithData:] kullanabilirsiniz. Bana açık olmayan (ve nasıl en iyi şekilde test edileceğinden emin değilim), hangi NSData nesnesinin temel malloc'd arabelleğine sahip olduğudır? Her ikisi de malloc tamponuna bir referans tutuyorsa (bir çeşit opak referans sayımı kullanarak) bu harika! Ancak, data nesnesi (freeWhenDone:YES tarafından belirtildiği gibi) yayımlandığında malloc tampon boşalırsa, data2 ellerinde sorun yaşayacaktır.

NSData bu durumda ne yaptığını açıklayabilir mi? Alternatif olarak, birileri bana neler olduğunu kanıtlamak için kesin bir test önerebilir mi? altta yatan soru için

+0

Veri ve veri için işaretçi adresini iyi bir şekilde kaydedin. NSLog (@ "% p% p", veri, data2) ;-) ;-) –

+0

@MatthiasBauch: Örnekteki son satır gibi mi demek istiyorsunuz? :-) ("NSLog" yerine printf "kullandım) –

+0

" YES ise, döndürülen nesne bayt işaretçisinin sahipliğini alır ve ayrılmadan serbest bırakır. " Bu bana, ilk NSData'nın ömrünün ötesinde hayatta kalan tampona güvenmemen gerektiğini söyledi. Ancak, muhtemelen ikinci NSData ilk NSData'nın referans sayısını artırır, bu nedenle ilk NSData ikinci olana kadar poof olmayacaktır. (ARC olmayanlarda bunu kontrol etmek için referans sayılarını test edebilirsiniz.) –

cevap

1

:

NSData içeriği ayrı ayrı referans sayılan mi

?

(No. Ama kodu baktığımızda,. Bu saptırma sonra aşağıya bakınız. Önemli olmamalı) ARC yönetir

--- Başlat Diversion ---

korur ve üzerine bültenleri Nesne-C nesneleri, uygun zamanlarda retain ve release iletilerinin eşdeğerini göndererek. "Uygun zamanlar", kod incelemesinde derleme zamanında belirlenir. Tam olarak yaptığı her şey budur. Bu nesnelerin nesne olmayan parçalarına (yani, bytes) işaretçiler oluşturmaya başladığınızda, yaşam süresini yönetmek için tek başınasınız.

@CouchDeveloper, objc_precise_lifetime hakkında iyi bilgiler sağlar. Bu özelliği veri nesnelerine yerleştirmek, dahili işaretçilerle çalışırken bir ARC optimizasyonundan sizi koruyabilir, ancak burada gerçekten alakalı değildir. objc_precise_lifetime'un noktası, referans değişkeninin kapsam dışı kalmasından önce bir nesnenin yayınlanmasına izin verilmediğini ARC'ye bildirmektir. o çözer sorun şuna benzer:

NSData *data = ...; 
void *stuff = data.bytes; // (1) 
doSomething(stuff); // (2) 

ARC hat arasındaki data yok etmesine izin söylüyor an optimization sahiptir (1) ve hat (2), sen data kapsamda olsa bile, yine data referans asla beri. objc_precise_lifetime özniteliğinin eklenmesi, bu optimizasyonu engeller. NSData'u kullanmaya başladığınızda, bu özellik önemli olabilir.

--- End Diversion ---

Tamam, ama ne durum hakkında?Bu kod çalıştırıldıktan sonra

float* cubeData = (float*)malloc(cubeDataSize); 
NSData* data = [NSData dataWithBytesNoCopy:cubeData length:cubeDataSize freeWhenDone:YES]; 
NSData* data2 = [data copyWithZone:nil] 

, iki olasılık vardır (ve bu değişmez nesneler olarak kullanılabildiğinden, doğrudur çoğu zaman bakım gerekiyordu değiliz):

  • data ve data2 aynı NSData nesnesine güçlü göstericilerdir. Bu nesne malloced belleğe sahiptir ve tahsis edildiğinde serbest bırakır. (Bu özel durumda gerçekleşmesi neredeyse kesin olan budur, ancak bu uygulama detayıdır.)
  • data, bozuk bellek olan bir NSData nesnesine işaret eder ve ayrılırken serbest bırakır. (. o ayırmanın ne zaman serbest olacak) kendi bellek ile farklı bir NSData nesneye data2 puan

(diğer seçenekler vardır; belki NSData altta yatan dispatch_data veya bir kopyası üzerinde yazma düzeni kullanır data kapsam dışına çıkarsa. fakat tüm seçenekler etkin ilk durumda). dışarıdan yukarıdaki gibi

bakmak gerekir, ancak data2, etrafında hala o sahip NSData korunmuş olmasıdır. Sorun değil. İkinci durumda, data kapsam dışına çıktığında, belleğini yok eder, ancak data2 bağımsız bir kopyasına sahiptir, bu nedenle sorun olmaz.

Sanırım, karmaşanızın data belleğe sahip olduğunu düşünmekten geliyor. Olmaz. dataNSData nesnesi, belleğin sahibi olduğunu gösterir. data ve data2 sadece işaretçilerdir.

+0

Benim karışıklığım, 'data' ve 'data2' nin aslında aslında aynı object_ 'i işaret ettiği gerçeğini, yani (tabii ki) içerdiği tamponun aynı olduğu gerçeğini kaçırmaktan geldi. Ben copyWithZone: 'yeni bir nesne döndüreceğini varsaymıştım, ama bunu yapmıyor (ya da bu durumda, yine de)[email protected] doğru yönde işaret etti ve cevabınız durumu daha ayrıntılı olarak açıklıyor. Teşekkürler! –

İlgili konular