内存泄漏问题

3

请问为什么我的代码会出现内存泄漏?

我已在代码中的分析器中添加了注释。如果有人能帮忙解决问题并解释一下为什么会出现这两个注释,我将不胜感激。

- (void)viewDidDisappear:(BOOL)animated {

// Empty array to be sure it is empty
[playerArray removeAllObjects];

//============CLEAN OUT DOUBLE NAMES FROM ARRAY==============//
NSArray *sortedDummyArray = [[NSArray alloc] initWithArray:selectedPlayersArray];
    ////>>>>The line above is line 84<<<<<<<////

// Sort the array
sortedDummyArray = [sortedDummyArray sortedArrayUsingSelector:@selector(compare:)];

NSMutableArray *finalArray = [[NSMutableArray alloc]initWithArray:sortedDummyArray];
    ////>>>>>> Possible memory leak on line 84 <<<<<<<<//// 



int xx = [sortedDummyArray count];
int yy;
int counter = 0;
int rr = 0;

for (int oo = 0; oo < xx; oo++) {
    yy = [finalArray count];

    for (int zz = 0; zz < yy; zz++) {

        // If hit, clean out the double name
        if ([[sortedDummyArray objectAtIndex:oo] isEqualToString:[finalArray objectAtIndex:rr]]) {

            counter++;

            // Check if there is more than one of this name
            if (counter > 1) {
                [finalArray removeObjectAtIndex:rr];
                rr--;
                counter--;
            }
        }
        rr++;
    }
    counter = 0;
    rr = 0;
}

[sortedDummyArray retain];

// Save who is in the game

AccessQuestionsDB *shufflePlayersFunction = [AccessQuestionsDB new];
finalArray = [shufflePlayersFunction shufflePlayers: finalArray];
[shufflePlayersFunction release];

TempPlayersInTheGame *savePlayersInTheGame = [TempPlayersInTheGame new];
[savePlayersInTheGame saveSelectedPlayers:finalArray];
[savePlayersInTheGame release];

[finalArray release]; //>>>> see comment below
    ////>>>>>Incorrect decrement of the reference count of an object that is not owned at this point by the caller <<<<<<///// 

    [sortedDummyArray release];
[super viewDidDisappear:animated];

}

3个回答

3

你的第一个泄漏是由于调用以下代码:

[sortedDummyArray retain];

您已经调用了一个执行此操作的alloc,但是您只在最后释放它一次(因此请删除上面的行)。然后,您重新分配它,这是不正确的。

您的第二个泄漏是由于您使用alloc设置了finalArray,然后用函数的结果替换了它。您可以通过替换此行来解决这个问题:

NSMutableArray *finalArray = [[NSMutableArray alloc]initWithArray:sortedDummyArray];

使用这个:

NSMutableArray *finalArray = [NSMutableArray arrayWithArray:sortedDummyArray];

然后删除这一行:

[finalArray release];

所以你的函数看起来应该像这样:

- (void)viewDidDisappear:(BOOL)animated {

    // Empty array to be sure it is empty
    [playerArray removeAllObjects];

    //============CLEAN OUT DOUBLE NAMES FROM ARRAY==============//   
    // Sort the array
    NSArray *sortedDummyArray = [selectedPlayersArray sortedArrayUsingSelector:@selector(compare:)];

    NSMutableArray *finalArray = [NSMutableArray arrayWithArray:sortedDummyArray];    

    int xx = [sortedDummyArray count];
    int yy;
    int counter = 0;
    int rr = 0;

    for (int oo = 0; oo < xx; oo++) {
        yy = [finalArray count];

        for (int zz = 0; zz < yy; zz++) {

            // If hit, clean out the double name
            if ([[sortedDummyArray objectAtIndex:oo] isEqualToString:[finalArray objectAtIndex:rr]]) {

               counter++;

               // Check if there is more than one of this name
               if (counter > 1) {
                   [finalArray removeObjectAtIndex:rr];
                   rr--;
                   counter--;
               }
            }
            rr++;
        }
        counter = 0;
        rr = 0;
    }

    // Save who is in the game

    AccessQuestionsDB *shufflePlayersFunction = [AccessQuestionsDB new];
    finalArray = [shufflePlayersFunction shufflePlayers: finalArray];
    [shufflePlayersFunction release];

    TempPlayersInTheGame *savePlayersInTheGame = [TempPlayersInTheGame new];
    [savePlayersInTheGame saveSelectedPlayers:finalArray];
    [savePlayersInTheGame release];

    [super viewDidDisappear:animated];
}

但是所有这些都是过度的,只是为了删除重复条目,将您的数组转换为NSSet(始终唯一),然后将其转换回NSArray应该为您处理此操作,因此您的函数应该是

- (void)viewDidDisappear:(BOOL)animated {

    // Empty array to be sure it is empty
    [playerArray removeAllObjects];

    //============CLEAN OUT DOUBLE NAMES FROM ARRAY==============//   
    NSSet *uniquePlayers = [NSSet setWithArray:selectedPlayersArray];

    // Save who is in the game

    AccessQuestionsDB *shufflePlayersFunction = [AccessQuestionsDB new];
    NSArray *finalArray = [shufflePlayersFunction shufflePlayers: [uniquePlayers allObjects]];
    [shufflePlayersFunction release];

    TempPlayersInTheGame *savePlayersInTheGame = [TempPlayersInTheGame new];
    [savePlayersInTheGame saveSelectedPlayers:finalArray];
    [savePlayersInTheGame release];

    [super viewDidDisappear:animated];
}

虽然我仍然会避免在不同的时间使用同一个指针指向两个不同的数组。但是,我不会在接近结束时重新设置finalArray;我会完全使用另一个指针来保存savePlayersInTheGame中的内容。这样做只是为了保持事情更简单。 - GendoIkari
非常感谢,这个论坛对像我这样的新人如此友好,真是太棒了 :-) - PeterK
2
@Gendolkari 我同意,我清理了内存泄漏以帮助说明它们的原因。但是针对这个特定问题(删除重复名称),我发布了一个更简单的解决方案,可以消除所有泄漏和指针重用。 - theChrisKent
@PeterK 很高兴能帮忙。请查看我的答案中的最终函数版本,以了解更简单的去除重复条目方法。 - theChrisKent

1

你的问题在于这一行:

finalArray = [shufflePlayersFunction shufflePlayers: finalArray];

早些时候,您正在内存中创建一个新数组,并告诉finalArray指向它。但是这里的这行代码告诉finalArray指向不同的东西。因此,现在,您创建的原始数组仍然存在于内存中,而且您正在释放不同的数组。

您还使用sortedDummyArray进行完全相同类型的操作。如果您分配了一个对象,请不要将指针设置为指向其他内容。


1

需要保留dummySortedArray的调用吗?我认为在初始化集合时,您可能已经对其进行了保留计数。

NSArray *sortedDummyArray = [[NSArray alloc] initWithArray:selectedPlayersArray];


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接