2

我正在使用 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

4 回答 4

2

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

不可能保留字节数组。只能保留对象。

我需要保留 NSData *数据吗?

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

让我们换个例子,看看如果你传入的是数据对象而不是字节,你会怎么做。

如果字符串确实保留了数据,那么您不必担心数据会从字符串中消失,因为字符串会保留它。如果它不保留它,则该字符串要么制作了自己的副本,要么根本不保存您的数据。

所以其他对象的保留无关紧要。不要担心他们。只关心谁拥有什么,并相应地保留或不保留。

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

好吧,您没有保留它,没有分配它,也没有复制它。因此,您不拥有它。所以不行。

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

于 2009-06-02T20:54:47.353 回答
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)
于 2012-03-27T15:57:22.420 回答
0

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

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

如果你想在离开方法后保留 NSString 对象,你应该保留它或通过像这样分配和初始化它来实例化它:
[[NSString alloc] initWithBytes:[...] length:[...] encoding:[. ..]]
这个 NSString 对象的保留计数也将是 1,但是当您不再需要它时,您必须显式释放它。

顺便提一句。[NSString stringWithCString:length:] 自 OSX 10.4 起已弃用

于 2009-06-02T12:23:58.167 回答
0

福尔克是正确的;你应该stringWithCString:encoding:改用。

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

当您使用便利构造函数时,NSString 的保留计数为 1,但已添加到自动释放池中,因此在您离开代码块后的某个时间,它将被释放。您不需要显式使用 alloc 和 init 方法来保留它。我的意思是,它是用 1 的保留计数创建的(但会自动释放)为 1。

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

于 2009-06-02T12:37:04.503 回答