如何修复内存泄漏?

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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

以上是关于如何修复内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 _NSCFNumber 的 iOS 内存泄漏?

如何修复 AFNetworking 3.1 中的内存泄漏?

如何修复内存泄漏?

如何修复 Valgrind 日志中的内存泄漏

如何修复 AttachedBehavior 上的 DependencyPropertyDescriptor AddValueChanged 内存泄漏?

如何修复 PHP 中的内存泄漏