【问题标题】:How do I reliably release memory in iPhone app?如何可靠地释放 iPhone 应用程序中的内存?
【发布时间】:2011-01-01 13:32:35
【问题描述】:

如果我有这个代码

 NSString *postData = [@"foo=" stringByAppendingString:fooText.text];
 ...
 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
 ...
 [postData release];   //this causes crash
 [request release];    //this causes crash

现在我知道这是expected behavior according to Apple's documents。现在,如果我删除发布代码,则不会发生崩溃,但我发现内存泄漏无论如何*request。所以我重写了代码

NSString *postData;
//postData = [NSString alloc];  // this line commented out since OP
postData = [@"foo=" stringByAppendingString:fooText.text];
...
NSMutableURLRequest *request;
request = [NSMutableURLRequest alloc];
request = [request initWithURL:url];
    ...
    [postData release];   //this still crashes #
    [request release];    //this works fine

我真的不明白为什么它会在 # 崩溃。这里有什么推荐的最佳实践吗?我想我一定遗漏了一些东西,因为我经常看到“速记”方法(顶部)发布(例如 Kochan,Objective-C 编程),但 Apple 文档说这是错误的。

【问题讨论】:

    标签: iphone memory


    【解决方案1】:

    一般的经验法则,如果您正在调用辅助静态方法(例如stringByAppendingString),那么您不应该释放它。该字符串在提供给您之前已添加到自动释放池中。如果你调用alloc 然后是init... 方法,那么你有责任释放那个对象。

    代码中需要注意的其他事项:

    • 在第二个示例中,您分配 postData,然后立即将其替换为由stringByAppendingString 创建的另一个字符串,这就是内存泄漏。
    • 您的发布调用有误,它们应该是[postData release][request release]
    • 在您的示例中,我没有看到 postDatarequest 之间有任何关联,因此不确定您对它们两个的确切了解。

    【讨论】:

    • "一般的经验法则,如果你正在调用一个辅助静态方法(例如 stringByAppendingString),那么你不应该释放它。"这就是我要找的!但是,鉴于仪器表明存在内存泄漏(这都在一个简单的方法中),我将如何在第一个示例中释放 *request。这似乎表明自动释放不适用于 *request。
    • 在第一个例子中,你自己分配和发起请求,所以你应该释放它。当你这样做时,你会遇到什么崩溃? EXC_BAD_ACCESS?这通常意味着您(或您提出请求的东西)已经发布了请求,而您没有意识到这一点。
    【解决方案2】:

    首先,在您的第二个示例中,postData = [NSString alloc]; 行是完全不需要的 - postData 被下一行覆盖。其次,要回答您关于为什么会崩溃的问题 - 没有好的答案 - 系统可以选择在保留计数达到 0 后随时释放内存。为了更轻松地调试问题,您应该打开 NSZombieEnabled,它将立即标记任何被释放的对象,为您提供 100% 可靠的方法来测试崩溃。

    另外,在单独的行上分配/初始化是不好的风格。

    一般来说,您应该专注于遵循内存准则。如果您不遵守准则,则行为可能是不确定的。

    【讨论】:

      【解决方案3】:

      为您的对象分配内存并在单行中更好地对其进行初始化 - init 方法可能会返回不同的对象,并且可能有助于避免您在第二个示例中犯的错误:

      NSString *postData; // Define pointer to string
      postData = [NSString alloc]; // Allocating nsstring pointer and assign it to variable
      postData = [@"foo=" stringByAppendingString:fooText.text]; // assign to postData new **autoreleased** string object. result of the previous assignment is abandoned.
      [postData release];  //so here you release autoreleased object!!
      

      我不知道为什么 [equest release];但是在第一个示例中会导致崩溃。

      附:我还没完全醒来,还是应该是[postData release] 而不是[release postData]

      【讨论】:

        【解决方案4】:
        NSString *postData;
        postData = [[NSString alloc]init];
        postData = [@"foo=" stringByAppendingString:fooText.text];
        ...
        NSMutableURLRequest *request;
        request = [[NSMutableURLRequest alloc]initWithURL:url];
        ...
            [postData release];   
            [request release]; 
        

        试试这个。

        【讨论】:

        • 您的示例仍然存在与原始问题相同的 postdata 问题
        • 最好添加[postData release];一旦你完成使用该变量。您必须在使用后释放内存。
        • postData 在第三行赋值后包含自动释放的对象 - 你不能释放它。并且您在第二行分配的字符串只是在您覆盖它时泄漏。
        • NSString *postData = [[NSString alloc]init]; postData = @"foo=%@",[fooText.text];这也可能被使用,请注意这可能不是您的问题的原因。
        猜你喜欢
        • 2010-12-06
        • 1970-01-01
        • 2013-02-09
        • 2017-11-02
        • 1970-01-01
        • 2010-09-26
        • 2017-05-14
        • 2015-11-06
        • 1970-01-01
        相关资源
        最近更新 更多