【问题标题】:How do I fix a memory leak?如何修复内存泄漏?
【发布时间】:2011-08-30 14:15:27
【问题描述】:

在进行长配置文件测试后,我发现在我的一个“.m”文件中,viewdidload 部分发生了内存泄漏。我检查并 xcode 突出显示了我用值初始化选择器数组的部分。我的程序使用选择器进行用户输入。我的程序中有 3 5 个不同的视图。第一个是免责声明,第二个是一个菜单,用户可以在其中选择他/她想要进行的计算类型。每个计算都需要用户从选择器输入的某些输入。例如。其中一个视图有 5 个输入,这些输入由 5 个不同的 uipicker 处理,这些 uipicker 具有用于保存值的单独数组。这些数组使用该视图的 viewdidload 方法中的值进行初始化。这是我在运行测试后发现的:

..................................................... ..................................................

这是我第一次开发应用程序,我有点不知道该怎么做。任何帮助,将不胜感激。

【问题讨论】:

    标签: objective-c xcode memory-management instruments


    【解决方案1】:

    目标 c 中的对象具有保留计数。如果在对象超出范围时(当您停止使用它时)此保留计数大于 0,则它会泄漏。

    以下事情会增加保留计数

    • [[alloc] 初始化]
    • 复制
    • [保留]
    • 将对象添加到数组中
    • 将对象添加为子对象(例如视图)
    • 可能还有更多,但您的代码中似乎没有使用任何其他内容

    以下减少保留计数

    • [发布]
    • 从数组中删除对象
    • 如果你释放一个数组,它的所有对象都会被释放

    您应该检查您的代码,并确保对数组的每个保留或添加都与相应的版本相匹配。 (可以在dealloc方法中释放成员变量)。

    编辑:杰里米提出了一个有效的观点,即我的回答没有

    一旦你将一个对象添加到一个数组中,它就会获得所有权,并在它完成后释放该对象。您需要做的就是确保根据内存管理规则释放您拥有的任何内容

    还有autorelease对象,看看这个例子;

    -(init){
        ...
        stagePickerArray = [[NSMutableArray alloc] init];
        for (int i = 0; i < 3; i++)
        {
            //this string is autoreleased, you don't have call release on it.
            //methods with the format [CLASS CLASSwithsomething] tend to be autorelease
            NSString *s = [NSString stringWithFormat:@"%d", i);
            [stagePickerArray addObject:s];
        }
        ...
     }
    

    我认为您唯一缺少的是在您的 dealloc 方法中调用 release

    -(void) dealloc
    {
        [stagepickerarray release];  //Do this for each of your arrays
        [super dealloc];
    }
    

    【讨论】:

    • 抱歉,这是误导。您不需要将添加到阵列的内容与发布相匹配。一旦你将一个对象添加到一个数组中,它就会获得所有权,并在完成后释放该对象。您需要做的就是确保根据内存管理规则释放您拥有的任何东西
    • 编辑引用您的评论以澄清
    • 非常感谢:)。我回去确保我保留的所有对象都正确释放,例如文本字段、选择器、工具栏等。我还为每个数组添加了一个释放,然后我再次运行测试。这次没有内存泄漏。但是我有一个问题,在测试期间我还检查了分配情况,总字节数为 9.3mb,活动字节数为 1.7mb,这正常吗?还是我应该担心?
    • FWIW,可以说自动释放的对象由最近的自动释放池“拥有”,最终将释放该对象(当池“耗尽”时)。 release 和 dealloc/free 是不一样的,所以如果还有其他对象的引用,还不会被dealloc-ed。只有当最后一个引用被释放,即保留计数达到 0 时,对象才会被“释放”(dealloc-ed)。
    • 另外,我倾向于使用类便利方法(那些以类名开头的方法,如stringWithFormat:arrayWithObjects:dictionaryWithObjects:forKeys: 等)用于临时 对象。这些通常返回自动释放的对象,所以当指向它们的指针离开作用域时,我不必担心释放它们。
    【解决方案2】:

    泄漏工具只会告诉您在哪里分配了它认为泄漏的对象。所以,它告诉你,例如,

    NSString* answer = [NSString stringWithFormat: ...
    

    分配一个永远不会被释放的对象。现在,-stringWithFormat: 给了你一个 you do not own 的对象,你似乎没有在任何地方保留它。因此,您不需要释放它,因此它不会自行泄漏。

    这意味着您拥有的其他东西必须保留它,而您永远不会释放其他东西。主要嫌疑人似乎是stagePickerArray。检查您是否在某处发布stagePickerArray。如果它是 -viewDidLoad 的本地变量,则必须在该方法结束之前释放或自动释放它。如果是实例变量,则必须在类的-dealloc方法中释放。

    【讨论】:

    • 谢谢 :) 我忘了为数组添加版本!这就是问题的原因!
    【解决方案3】:

    在 Objective-C 中,您需要注意分配内存的保留计数。如果你不需要它-> 释放它。

    当你分配一个对象时,它会返回一个retain count = 1的对象。

    通过使用保留,保留计数增加, 通过使用释放,保留计数会减少。 每当保留计数等于 0 时,对象就会被销毁。

    因此,每当您想在其他地方使用该对象时,您都需要保留它。因此,您要确保在另一个“人”(或它使用的任何东西;))调用释放之后,该对象不会被删除。

    这是一个非常非常非常简短的描述。检查以下指南 Memory Management Guide for iOS.

    (您还想阅读有关 ARC - Automatic Retain Counting - 这是 iOS5 中的新功能!ios5 best practice release retain

    【讨论】:

    • 谢谢你:)。我会看看那个! .我目前正在使用 iOS 4 xD
    猜你喜欢
    • 2012-01-12
    • 2018-05-09
    • 2018-07-12
    • 2012-09-14
    • 2020-05-24
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多