gpt4 book ai didi

ios - NSData的内容是单独引用计数的吗?

转载 作者:可可西里 更新时间:2023-11-01 04:52:52 24 4
gpt4 key购买 nike

我有一个很大的 malloc'd 区域,我想将其包装在 NSData 对象中。一段时间后,我复制了那个 NSData 对象。我希望这两个 NSData 对象具有独立的生命周期。 ARC 负责对 NSData 对象本身进行引用计数,但我试图阐明包含的 malloc 区域 的生命周期。这是一个代码草图:

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

我认为 copyWithZone 不会深度复制 malloc 区域,我可以使用 [NSData dataWithData:] 如果我想要深度复制。我不清楚(而且我不确定如何最好地测试)是哪个 NSData 对象拥有底层的 malloc 缓冲区?如果它们都持有对 malloc 缓冲区的引用(使用某种形式的不透明引用计数),那就太好了!但是如果 malloc 的缓冲区在 data 对象被释放时被释放(正如 freeWhenDone:YES 暗示的那样),data2 将在它的手。

谁能解释一下 NSData 在这种情况下做了什么?或者,有人可以建议一个确定的测试来向我自己证明发生了什么吗?

最佳答案

基本问题:

Is the content of NSData separately reference-counted?

没有。 (但是看看你的代码,这应该无关紧要。在这种转移之后见下文。)

---开始转移---

ARC 通过在适当的时间发送等同于 retainrelease 的消息来管理 Objective-C 对象的保留和释放。 “适当的时间”是在编译时通过代码检查确定的。这正是它所做的一切。当您开始创建指向这些对象的非对象部分(即 bytes)的指针时,您需要自己管理生命周期。

@CouchDeveloper 提供了关于objc_precise_lifetime 的有用信息。将此属性放在数据对象上可以保护您在处理内部指针时免受 ARC 优化的影响,但它在这里并不真正相关。 objc_precise_lifetime 的目的是告诉 ARC 在引用变量超出范围之前不允许释放对象。它解决的问题如下所示:

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

ARC 有 an optimization这表示允许销毁第 (1) 行和第 (2) 行之间的 data,因为您再也不会引用 data,即使 data 是在适用范围。添加 objc_precise_lifetime 属性会禁止该优化。当您开始大量使用 NSData 时,此属性会变得很重要。

---结束转移---

好的,但是你的情况呢?

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

这段代码运行后,有两种可能性(大多数时候你不应该关心这是真的,因为它们是不可变的对象):

  • datadata2 都是指向同一个 NSData 对象的强指针。该对象拥有分配的内存,并在释放时释放它。 (在这种特殊情况下几乎肯定会发生这种情况,但这是一个实现细节。)
  • data 指向一个 NSData 对象,该对象拥有 malloced 内存并将在释放时释放它。 data2 指向一个不同的 NSData 对象,它有自己的内存(当 it 被释放时它会被释放。)

(还有其他选项;也许 NSData 使用底层 dispatch_data 或写时复制方案。但是所有选项都应该像上面的那样有效外面。)

在第一种情况下,如果 data 超出范围,但 data2 仍在附近,则保留拥有的 NSData。没问题。在第二种情况下,当 data 超出范围时,它会破坏它的内存,但是 data2 有它的独立副本,所以也没有问题。

我认为您的困惑来自于认为 data 拥有内存。它没有。 data 指向的 NSData 对象拥有内存。 datadata2 只是指针。

关于ios - NSData的内容是单独引用计数的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17661719/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com