NSString stringWithCString:length:保留我传入的字节数组吗?

时间:2009-06-02 07:59:49

标签: cocoa memory-management nsstring

我正在使用AsyncSocket,其中AsyncSocket对象在从远程端接收数据时调用下面的委托方法:

- (void)onSocket:(AsyncSocket*)socket didReadData:(NSData*)data withTag:(long)tag;

现在,在此方法中,我将NSData对象传递给以下命令以获取所接收数据的NSString表示:

NSString *body = [NSString stringWithCString:[data bytes] length:[data length];

NSString stringWithCString:length:保留我传入的字节数组吗?我需要保留NSData *数据吗?我是否需要在最后释放NSString * body?

感谢。我希望在委托方法方面正确地进行内存管理......

4 个答案:

答案 0 :(得分:2)

  

NSString stringWithCString:length:保留我传入的字节数组吗?

无法保留字节数组。只能保留对象。

  

我是否需要保留NSData *数据?

没有。因为字符串无法保留数据(它不知道)或其内容,所以字符串将复制字节。 (想想如果你实现这个方法你会怎么做:就是这样。)

让我们改变一下情况,看看如果你传入数据对象,你会做什么,而不是字节。

如果字符串确实保留了数据,那么您不必担心从字符串下面消失的数据,因为字符串保留了它。如果它没有保留它,那么字符串要么自己制作副本,要么根本不保留你的数据。

所以其他物品的保留并不重要。别担心他们。只担心谁拥有什么,并相应保留或不保留。

  

我是否需要在最后释放NSString * body?

嗯,你没有保留它,你没有分配它,你没有复制它。因此,你不拥有它。所以,没有。

如果您确实想拥有该对象的所有权,您可以保留它或制作(然后拥有)您自己的副本。然后你会释放它。

答案 1 :(得分:1)

简单回答证明。 NSString stringWithCString:encoding:复制字节缓冲区以生成字符串。缓冲区由你来维护。

证明:

代码:

    const char* hardString = "Hello, World";
    char *buffer = nil;

    buffer = calloc(13, 1);
    bzero(buffer, 13);

    memcpy(buffer, hardString, 12);

    NSString *aString = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];        
    NSLog(@"aString: %@  \t filled buffer:(%p) [%s]", aString, (void*)buffer, buffer);

    bzero(buffer, 13); 
    NSLog(@"aString: %@  \t zeroed buffer:(%p) [%s]", aString, (void*)buffer, buffer);

    free(buffer);
    NSLog(@"aString: %@  \t free'd buffer:(%p)", aString, (void*)buffer);

    buffer = nil;        
    NSLog(@"aString: %@  \t nulled buffer:(%p)", aString, (void*)buffer);

结果:

aString: Hello, World    filled buffer:(0x10010a790) [Hello, World]
aString: Hello, World    zeroed buffer:(0x10010a790) []
aString: Hello, World    free'd buffer:(0x10010a790)
aString: Hello, World    nulled buffer:(0x0)

答案 2 :(得分:0)

您不必保留NSData数组,因为其内容将被转换/复制到新的NSString对象中。

返回的NSString对象的保留计数为1,但已添加到自动释放池中。
这意味着一旦自动释放池被销毁,它将自动释放。如果您使用的是AppKit创建的默认自动释放池,则会在当前事件循环处理结束时发生。所以,如果你只在那个方法“onsocket:...”中使用这个字符串对象,你就可以了。

如果要在离开方法后保留NSString对象,则应保留它或通过分配和初始化它来实例化它:
[[NSString alloc] initWithBytes:[...] length:[...]编码:[...]]
此NSString对象的保留计数也为1,但是当您不再需要它时,必须明确释放它。

顺便说一下。 [NSString stringWithCString:length:]自OSX 10.4起不推荐使用了

答案 3 :(得分:0)

Pholker是正确的;你应该使用stringWithCString:encoding:代替。

仅对物体需要保留/释放;当你传入一个C字符串(它不是一个对象,不像NSString)时,没有什么可以保留或释放。

当您使用便利构造函数时,NSString的保留计数为1,但会添加到自动释放池中,因此在您离开代码块后的某个时间,这将被释放。您不需要显式使用alloc和init方法来保留它。我的意思是,它创建的保留计数为1(但将被自动释放)如果你在上面调用retain,那么会将计数增加到2,但在某个时间之后,它将被自动重新计算,并且保留计数将会下降到1。

如果你没有在一个对象上调用init,retain,copy或mutableCopy,你可以假设它将被自动释放,你不需要显式释放任何东西。但是如果你想保留一个代码块之外的对象,你需要调用retain然后稍后释放它(通常是在创建对象的类的dealloc方法中)。