2012-01-01 1 views
5

Я хочу, чтобы иметь буфер данных длиной затруднительное изменяемые контента совместно и как я могу его создать:Поведение NSData initWithBytesNoCopy: длина: freeWhenDone:

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

Что произойдет, если я изменить buffer после того как я создал NSData от него? Будет ли NSData отражать изменение, которое я сделал с buffer?

Я могу гарантировать, что sharedData не получит dealloc, если я хочу изменить buffer.

Это, как я на самом деле хочу, чтобы использовать его:


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); 

ответ

7

initWithBytesNoCopy: эффективно создать NSData оболочку вокруг существующего буфера; так что да, все, что доступно через [sharedData bytes], будут видеть любые сделанные вами обновления.

Конечно, это не делает ничего, чтобы связать другие объекты, которые создаются из экземпляра NSData, так, например, [NSImage initWithData:sharedData] может сделать копию для NSImage экземпляра, который не будет отражать любые изменения.

Кроме того, с freeWhenDone:YESNSData уничтожит буфер, когда последняя ссылка удаляется, поэтому обратите внимание на что =)


Таким образом, учитывая, что NSData эффективно тонкая обертка вокруг malloc() распределения , да, это отразит изменения, внесенные в эту память (любым способом); но, как он назовет free(), это плохая идея использовать его для обертывания созданного буфера другим способом (mach_vm_allocate) с freeWhenDone:YES.

Если вы не очень-очень нужно использовать пользовательский распределитель, я думаю, вы бы лучше с (почему?):

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. 
Смежные вопросы