【问题标题】:Leak in NSMutableArray category that returns array filled with NSNullNSMutableArray 类别中的泄漏,返回用 NSNull 填充的数组
【发布时间】:2011-04-13 16:44:53
【问题描述】:

我目前有一个 NSMutableArray 类别,它创建一个使用 NSNulls 传播的 NSMutableArray。当我在 Instruments 中运行此代码时,它告诉我这里有泄漏(阅读评论以查看位置)

#import "NSMutableArray+NSNull.h"


@implementation NSMutableArray (NSNull)

-(id)initWithNullCapacity:(int)capacity{

    self = [super init];
    if (self) {
        //Leak on [self init]
        NSMutableArray *array = [self init];

        for (unsigned i = 0; i < capacity; i++)
        {
            [array addObject:[NSNull null]];
        }
        self = array;
    }
    return self;
}

编辑:

这是我调用方法的地方:

#import "TWVStatData.h"
#import "NSMutableArray+NSNull.h"

@implementation TWVStatData

@synthesize creationTime;
@synthesize graphs;
@synthesize elements;
@synthesize type;

-(id)init{
    if(self == [super init]){
        type = -1;

        creationTime = [[NSDate alloc] init];

        graphs = [[NSMutableArray alloc] initWithNullCapacity:3];
        elements =[[NSMutableArray alloc] init];
    }
    return self;
}

【问题讨论】:

    标签: iphone ios memory-management memory-leaks


    【解决方案1】:

    这会很棘手,主要是因为NSArray 在下面是如何工作的。我建议这样做:

    - (id)initWithNullCapacity:(NSUInteger)capacity {
      NSMutableArray *nulls = [NSMutableArray array];
      for (NSUInteger i = 0; i < capacity; i++) {
        [nulls addObject:[NSNull null]];
      }
      return [self initWithArray:nulls];
    }
    

    我认为问题出在分配给self 的问题上,尽管我不确定。 NSArray 在后台做了一些时髦的优化,所以我会避免调用 NSArray 初始化器,直到之后你准备好所有数据。

    【讨论】:

    • 当我在 Instruments 中运行你的代码时,我得到一个在线返回 [self initWithArray:nulls];经过反复试验,我设法通过我作为答案发布的实施来修复它。
    • @Cyprian 那么你做错了什么,因为当我以孤立的方式使用它时,它可以完美地工作而没有泄漏。
    • +1 看起来不错,但我想代价是在内存中保留 2 个数组而不是一个数组,而不是我认为它会造成任何实际影响
    【解决方案2】:

    您没有创建 NSMutableArray 的子类,只是添加了一个类别,因此调用 [super init] 将调用 NSArray 而不是 NSMutableArray 初始化程序,无论它做什么,我都会调用它,以防它做一些重要的事情。

    另外,正如 Ravin 所提到的,设置 self = 而不首先调用 [self release] 会泄漏前一个对象,该对象是从调用堆栈中上一级的 alloc 调用返回的。

    这是你应该做的:

    -(id)initWithNullCapacity:(int)capacity
    {
        self = [self initWithCapacity:capacity];
        if (self) 
        {
            for (int i = 0; i < [self count]; i++)
            {
                [self addObject:[NSNull null]];
            }
        }
        return self;
    }    
    

    【讨论】:

    • 当我按照您的建议进行操作时,仪器告诉我 self = [self initWithCapacity:capacity];
    • @Cyprian 你能贴出使用这种方法的代码吗?真的不应该有什么问题……
    • 你说得对,我在初始化层次结构中较高的对象时出错,但没有释放它,导致较低的对象发生泄漏。
    【解决方案3】:

    是的,因为在第一行

    self = [super init];
    

    您正在创建一个对象 (self) 并且在 self = array; 您正在取消引用 self 并重新分配它。所以早期的价值在泄漏。

    【讨论】:

    • 谢谢,但你能明确告诉我在方法中要改变什么吗?
    【解决方案4】:
    -(id)initWithNullCapacity:(int)capacity
    {
        self = [super init];
        if (self) {
            for (unsigned i = 0; i < capacity; i++)
            {
                [self addObject:[NSNull null]];
            }
        }
        return self;
    }
    

    应该做的工作

    【讨论】:

    • 好吧,当我这样做时,编译器会给我一个错误:-[NSMutableArray count]: method sent to an uninitialized mutable array object
    猜你喜欢
    • 2011-02-24
    • 2011-10-15
    • 2011-06-23
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多