【问题标题】:Releasing a returned-by-reference NSString causes crash释放引用返回的 NSString 会导致崩溃
【发布时间】:2011-10-31 14:41:24
【问题描述】:

以下方法接受一个指向NSString 的双指针并用一个值填充它,如下所示:

@implementation Exp
- (int) func:(NSString**) dpStr
{
    //------
    *dpStr = [self func_2];
    //------
}

现在它是这样调用的:

int main ()
{
   NSString * str = [[NSString alloc] init];
   int retCode = [Exp func:&str];
   // <----- Now here I'm able to access value returned by func ------->

   [str release];    //  <--- It is crashing here 
}

谁能解释一下为什么会崩溃?

【问题讨论】:

    标签: objective-c ios memory-management nsstring return-by-reference


    【解决方案1】:

    这会分配一个空字符串:

    NSString * str = [[NSString alloc] init];
    

    这替换 str 的先前值,用一个显然已经自动释放的新字符串; str 的旧值泄露:

    int retCode = [Exp func:&str];
    

    这会尝试释放str 的新值,该值已经平衡,因此它是过度释放并发生崩溃:

    [str release];
    

    在这种情况下,既不需要前导 +alloc/-init 也不需要尾随 -release,因为对象由 -func: 提供。您只需要:

    NSString *str = nil;
    [Exp func:&str];
    // use str normally
    

    最好修改-func:直接返回字符串:

    NSString *str = [Exp func];
    // use str normally
    

    那么就不用地址传了。

    【讨论】:

    • 如果我用 NSMutableString 替换 NSString 并在函数中执行以下操作 - (int) func:(NSMutableString**) dpStr { ------ [*dpStr setString:[self func_2]]; ------ } 然后我可以使用 [str release] 释放内存。这个乐趣是在库中定义的,我从我的应用程序中调用这个乐趣,该应用程序与这个库静态链接推荐哪种方法......
    • 推荐的方法是我在回答中描述的。在 Objective-C 中,您不需要为字符串等提供缓冲区;操作系统通常会为您处理。
    • 请建议我应该为 iOS 应用程序采用哪种方法
    • 我已经做过了。 iOS 与这里的任何其他 Objective-C 目标没有什么不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2012-10-11
    相关资源
    最近更新 更多