2012-01-01 7 views
5

chcę mieć bufor danych długość fix zmienny treści udostępniane i to w jaki sposób mogę utworzyć go:Zachowanie NSData initWithBytesNoCopy: długość: freeWhenDone:

void *buffer = malloc(length); 
// initialize buffer content 
NSData *sharedData = [[NSData alloc] initWithBytesNoCopy:buffer length:length freeWhenDone:YES] 

Co się stało, gdybym modyfikować buffer po Stworzyłem NSData z tego? Czy NSData będzie odzwierciedlać zmianę, którą wprowadziłem dla buffer?

Mogę zagwarantować, że sharedData nie otrzyma dealloc, gdy chcę zmodyfikować buffer.

ten sposób faktycznie chcę go używać:


void *my_alloc(CFIndex allocSize, CFOptionFlags hint, void *info) {return NULL;} 
void my_dealloc(void *ptr, void *info) { 
    mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)ptr, (size_t)info); 
} 

size_t length = //some number 
mach_vm_address_t buffer; 
mach_vm_allocate(mach_task_self(), &buffer, length, VM_FLAGS_ANYWHERE); 
// do something to buffer, for example pass to other process using mach RPC and expect other process will modify the content 
CFAllocatorContext context = {0, (void *)length, NULL, NULL, NULL, my_alloc, NULL, my_dealloc, NULL}; 
CFAllocatorRef allocator = CFAllocatorCreate(NULL, &context); 
CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)buffer, length, allocator); 

Odpowiedz

7

initWithBytesNoCopy: skutecznie stworzyć NSData otoki wokół istniejącego bufora; więc tak, rzeczy uzyskujące dostęp przez [sharedData bytes] zobaczą wszystkie aktualizacje, które wprowadzasz.

Oczywiście nic nie łączy z innymi obiektami utworzonymi z instancji NSData, więc na przykład [NSImage initWithData:sharedData] może utworzyć kopię dla instancji NSImage, która nie będzie odzwierciedlała żadnych zmian.

Również z freeWhenDone:YESNSData zniszczy bufor gdy ostatni przywołuje się usunąć, tak zwrócić uwagę na to =)


Tak więc, biorąc pod uwagę, że NSData jest w rzeczywistości cienkie owinięcia alokacji malloc() , tak, będzie odzwierciedlać zmiany wprowadzone do tej pamięci (dowolnym procesem); ale jak to nazwiemy na free(), nie jest dobrym pomysłem użycie go do zawijania bufora utworzonego w inny sposób (mach_vm_allocate) z freeWhenDone:YES.

Jeśli nie naprawdę, naprawdę trzeba użyć niestandardowego przydzielania, myślę, że będziesz lepiej z (dlaczego?):

NSMutableData* sharedData = [NSMutableData dataWithCapacity:length]; 
// `dataWithLength:` will fully allocate and zero the buffer first, if you prefer 
void* buffer = [sharedData mutableBytes]; 
// do something to `buffer`, mach RPC, etc. 
// 3: profit.