【问题标题】:iPhone - Memory leak while displaying UILabeliPhone - 显示 UILabel 时内存泄漏
【发布时间】:2009-11-23 10:39:48
【问题描述】:

我正在使用一个简单的函数通过标签向用户显示消息。函数如下:

-(void) showMessage:(NSString*) message
{  
    Message.text = message;
    [message release]; 
}

如果我从主线程调用此函数,则不会发生内存泄漏。但是,如果我从单独的线程调用此函数,则仪器监视器会在调用该函数后立即显示 16 字节的内存泄漏。如果我注释掉函数调用,则看不到泄漏。有谁知道为什么?我正在使用 iPhone SDK 3.0。仪器监视器没有指向我的任何功能来指示泄漏。它只显示 UILabel 中的一两个函数。

【问题讨论】:

    标签: iphone objective-c memory-leaks uilabel


    【解决方案1】:

    查看那里的代码,您似乎在某处出现了内存管理错误 - 您应该永远 release 作为方法参数接收的对象。考虑以下几点:

    -(void)doSomething {
    
        NSString *aStr = [[NSString alloc] init];
    
        [self showMessage:aStr];
    
        NSString *anotherStr = [aStr stringByAppendingString:@"Hi"];
        // ^^ This call will crash as aStr has been released and is invalid.
    }
    
    -(void) showMessage:(NSString*) message {
        Message.text = message; 
        [message release];
    }
    

    ... 在上面的例子中使用你的方法会导致崩溃,因为 showMessage: 方法释放了传递的字符串。

    我知道这并不能直接回答您的问题,但是如果正确进行内存管理,您的问题可能会消失。我建议你阅读苹果的Memory Management Programming Guide for Cocoa

    编辑:另外,UIKit 不是线程安全的——你不应该从除主线程之外的任何地方调用 UIKit 对象的消息。请参阅performSelectorOnMainThread:withObject: 以从另一个线程调用主线程上的消息。

    【讨论】:

    • iKendac 做对了。从您的代码中删除 [消息发布]。
    • 在我的项目中,我使用了大量的消息来向用户抛出。所以我将它们全部保存在一个“常量”文件中,例如: NSString * const testString = @"Hello";然后我将此 testString 传递给 showMessage 函数。我是否进行[消息发布]都没有关系。我评论了那条线,泄漏仍然存在。我试过 [self performSelectorOnMainThread:@selector(showMessage) withObject:yourTurn waitUntilDone: NO];但它不显示消息,并在下一次用户交互时崩溃。我再说一遍,从主线程调用该函数时不会泄漏。
    【解决方案2】:

    很难从这段代码中弄清楚。此外,仪器并不是一种完美的机制,当然不能用于发现(和解决)这种大小的泄漏。

    这可能甚至不是泄漏,但这取决于您在函数调用之前和之后如何初始化和释放消息字符串。

    如果你这样初始化它;

    NSString *message = [[NSString alloc] initWithString:@"hello"];
    

    消息将收到 +1 的保留计数,并且您必须在将其作为参数传递给您的函数后释放它。在函数内部,它将被标签再次保留。如果您使用自动释放消息对其进行初始化,那么情况就完全不同了。

    此外,当您使用 NSThread 时,请在您的方法中使用 NSAutoreleasePool。

    我还建议运行 XCode 的静态分析器,它可以帮助您发现不当的内存管理。

    【讨论】:

    • 在我的项目中,我使用了大量的消息来向用户抛出。所以我把它们都保存在一个“常量”文件中,比如: NSString * const testString = @"Hello";然后我将此 testString 传递给 showMessage 函数。我是否进行[消息发布]都没有关系。我评论了那条线,泄漏仍然存在。我尝试使用 clang 静态分析器。它没有给我任何泄漏。这个小漏可以吗?我的意思是,我可以忽略它吗?
    • 如果是常量,请跳过[消息发布]部分。如果 Message 是 UILabel,它将在感觉合适时保留(并释放)该消息。泄漏仪器不是世界上最好的,我建议假设静态分析仪的结果是真实的。
    猜你喜欢
    • 2010-10-23
    • 2010-11-23
    • 2011-12-10
    • 2011-05-24
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多