stringByAppendingString并保留两难境地

时间:2013-07-08 21:22:23

标签: objective-c cocoa nsstring retain autorelease

我将发布一个使用自动释放着名方法stringByAppendingString的示例方法的下行3变体。(xcode 4.6.2.IOS项目中的非弧样本项目)

示例块1:不返回任何内容。只有奇怪的指向什么都没有。但不是空。
样本块2:也不返回任何内容! 样本块3:返回A1A2A3。正如所料,但我认为它有泄漏
我的问题是:
a)样本方法1在MAC项目中按预期工作。但不在IOS项目中。
b)是样本块3 - 包括泄漏?
c)查看样本块2中的注释.word_变为A1,A1A2和nothing.why?
d)你会以不同的方式用自己的方法编写自己的相同方法吗?。我正在寻找安全的标准方法。

感谢。

<小时/> 样本块1

-(NSString*)sampleMethod
{
    NSString *word_=@"";
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    word_=[word_ stringByAppendingString:a1];// word_ is A1
    word_=[word_ stringByAppendingString:a2];// word is nothing but another pointer
    word_=[word_ stringByAppendingString:a3];// word is nothing too but pointer changed.
    return word_;
}

样本块2

-(NSString*)sampleMethod
{
    NSString *word_=@"";
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    word_=[word_ stringByAppendingString:a1];// word_ is A1
    word_=[[word_ stringByAppendingString:a2]retain];// word is A1A2
    word_=[[word_ stringByAppendingString:a3]retain];// word is nothing !
    return word_;
}

样本块3

-(NSString*)sampleMethod
{
    NSString *word_=@"";
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    word_=[[word_ stringByAppendingString:a1]retain];// word_ is A1
    word_=[[word_ stringByAppendingString:a2]retain];// word_ is A1A2
    word_=[[word_ stringByAppendingString:a3]retain];// word_ is A1A2A3
    return word_;//returns as expected but I think leaks method in this method.
}

<小时/> 我的答案:仅仅因为我没有做错任何事。并且调试过程步骤收集的变量值非常明显。

但不知何故,它在干净的project.hope之后解决了。这可能会为某些人节省时间。或者不知道内存芯片地址可能出现了问题。

3 个答案:

答案 0 :(得分:4)

第一个是使内存管理正确的唯一方法。第二个泄漏两个,第三个泄漏三个NSString实例。如果你没有从第一个方法得到字符串“A1A2A3”,那么错误就在那个方法之外的某个地方。

对于您发送的每条保留消息,您还必须以相同的方法发送版本或自动释放消息,除非您的方法名称以alloc或copy开头。在这种情况下,调用者需要释放返回的对象。

答案 1 :(得分:3)

  

a)哪个样本区块3 - 包括泄漏?

样本中-retain的每次使用都是意外的,可能会导致泄漏。

  

b)查看Sample Block.word_中的注释变为A1,A1A2和nothing.why?

请仔细检查一下。

  c)你会以不同的方式用同一种方法编写自己的代码吗?。我正在寻找安全的标准方法。

您可以使用可变字符串,例如:

- (NSString*)sampleMethod
{
    NSMutableString * word = NSMutableString.string;
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    [word appendString:a1];
    [word appendString:a2];
    [word appendString:a3];

    return [NSString stringWithString:word];
}

或格式字符串:

- (NSString *)sampleMethod
{
    NSString *a1=@"A1";
    NSString *a2=@"A2";
    NSString *a3=@"A3";

    return [NSString stringWithFormat:@"%@%@%@", a1, a2, a3];
}

然后根据您的实际输入进行混合和匹配。

答案 2 :(得分:2)

第二个和第三个块包含泄漏。一般规则是你保留你想拥有的东西,并在你不再需要它时释放它。第一个块完全正常:你正在返回一个自动释放的字符串,如果他想拥有它,将由调用者保留,否则,它将在第一个将要清理的自动释放池中释放。

在第二个区块中你正在这样做:

word_=[[word_ stringByAppendingString:a2]retain];// word is A1A2
word_=[[word_ stringByAppendingString:a3]retain];// word is nothing !

字符串@“A1A2”的保留计数为2,在下一次自动释放池排放时它的保留计数为1,但是你丢失了对它的任何引用,所以它是一个泄漏。至于保留字符串@“A1A2A3”,这也是不正确的:调用者将决定是否要保留它。由于同样的原因,第三个块是不正确的。