我的代码中有很大的二进制资源,已使用bin2c类型程序将其转换为数组。

以前,我们使用[NSData dataWithBytes:raw length:rawLength]读取资源(例如)。

这是一个非常大的数组(> 32KB),目前加载和使用此资源的整个过程很慢,因此我尝试在可以的地方节省时间(不,我现在还没有显式地描述副本vs noCopy时间)。

我只是在想,因为dataWithBytesNoCopy:接受void*而不是const void*,这是否意味着从常量源使用它是不安全的(在这种情况下,它已编译为程序可执行文件)。

我不认为这是NSData开发人员的疏忽,因为initWithBytes:dataWithBytes:都将const void*作为参数-考虑到NSData本身是不可变的,当NSData不是const时,NSData会对输入数据做些什么(如果有的话)?

我想知道是否为与NSMutableData向前兼容而将参数定义为不是const

最佳答案

从理论上讲,[NSData dataWithBytesNoCopy:…]被映射到CFDataCreateWithBytesNoCopy()或类似的低级函数,其文档进一步介绍了如何处理原始字节:

讨论区
此函数从非结构化字节的缓冲区中创建一个不变的CFData对象。除非情况另有要求,否则创建的对象不会将外部缓冲区复制到内部存储,而是将缓冲区用作其后备存储。但是,您永远不要指望使用外部缓冲区的对象,因为它可以将缓冲区复制到内部存储器,甚至可能完全转储缓冲区并使用其他方式存储字节。

换句话说,可以复制缓冲区,并且您不能依赖于将对原始缓冲区的更改“传播”到NSData,但这不是问题。原始问题仍未得到解答:是否会就地修改原始字节(尽管现在提示可能已经很明显了)。
更新:
如果情况允许,您可以只加载一次NSData,然后仅在热循环中将其复制(复制很便宜,因为NSData是不可变的并且共享内容)。

static const char *myBytes = "myBytes here...";
static NSData *myData = nil;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    myData = [[NSData alloc] initWithBytes:myBytes length:strlen(myBytes)]; // EDIT: still need to copy to be clean
});

for (int i = 0; ; i++) {
    NSData *hotLoopData = [myData copy];
    NSData *hotLoopData = [[NSData alloc] initWithData:myData];
}

关于ios - 使用[NSData dataWithBytesNoCopy:…freeWhenDone:NO]与const字节数组作为输入是否安全?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21152982/

10-14 22:40