简体   繁体   English

内存泄漏NSMutableArray,NSArray,iPhone SDK中的NSString

[英]Memory leak in NSMutableArray, NSArray, NSString in iPhone SDK

In my app, I got Memory leaks in NSMutableArray, NSArray and NSString. 在我的应用程序中,我在NSMutableArray,NSArray和NSString中出现内存泄漏。

Here is the code. 这是代码。

    NSString *subQuery = [NSString stringWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName];
    NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease];        
    [subArray addObjectsFromArray:subArray1];

    NSString *columnQuery = [NSString stringWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName];
    NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];
    [langArray addObjectsFromArray:newArray];

    NSMutableArray *tempArray = [[NSMutableArray alloc] init];

    for (int i=0; i<[newArray count]; i++) {
        NSString *cellText = [[newArray objectAtIndex:i] valueForKey:[NSString stringWithFormat:@"%@",lblshortName.text]];

        if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""] ) {
            NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];

            [tempArray addObject:[NSString stringWithFormat:@"%@ : %@",lblshortName.text, decodedString3]];
        }
        else {
            [tempArray addObject:@"<empty>"];
        }

        NSString *detail = @"_________________";

        for (int j=0; j<[lableNameArray count]; j++) {

            NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:[NSString stringWithFormat:@"%@",[lableNameArray objectAtIndex:j]]];

            if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
            {
                NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
                detail = [NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4];
            }               
        }   
        [detailTextArray addObject:detail]; 

    }

When I run in Instruments I got leaks in 当我在仪器中运行时,我发现了泄漏

-subArray1 in second line. -subArray1在第二行。

-detail (NSString) in second for loop. -detail(NSString)在第二个for循环中。

And subArray and langArray are my global arrays. subArray和langArray是我的全局数组。

If I remove mutableCopy from NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; 如果我从NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];删除mutableCopy NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; and NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; then subArray and langArray doesnot retain values. 然后subArray和langArray不保留值。

How to avoid memory leak in this code? 如何避免此代码中的内存泄漏?

Not sure what is causing the memory leak, but this may help. 不确定是什么导致内存泄漏,但这可能会有所帮助。 This is a more direct way of copying the arrays, and may result in avoiding the leak: 这是一种更直接的复制数组的方法,可能会避免泄漏:

NSArray *langArray =[[NSArray alloc] initWithArray: [self returnExecuteQuery:columnQuery] copyItems: YES];

This basically makes a one-level deep copy of the array returned by returnExecuteQuery. 这基本上是由returnExecuteQuery返回的数组的一级深层副本。 You can read about it in more detail in Collections Programming Topics . 您可以在“ 集合编程主题”中更详细地阅读它。

I'm not sure how mutableCopy works and that may have something to do with the leak. 我不确定mutableCopy是如何工作的,这可能与泄漏有关。 If it copies the objects in the old array & then adds them to the new array, they may enter the array with a retain count of 2 (1 from the copy, and 1 from being added to an array.) It doesn't make much sense that it should work this way. 如果它复制旧数组中的对象然后将它们添加到新数组,它们可能会进入数组,其保留计数为2(副本为1,而数组为1)。很有意义,它应该这样工作。 But, if it does, that could account for the leak. 但是,如果确实如此,那可能是造成泄漏的原因。

Olease try this one, in above code you are creating two many objects that belong to autorelease pool here is one version where I tried to handle release of those string variables. 请试试这个,在上面的代码中你创建了两个属于自动释放池的对象,这里是我试图处理那些字符串变量释放的一个版本。

Second this is that the leak of detail is because you are de-referencing it many times in your code. 其次, detail的泄漏是因为您在代码中多次取消引用它。 And for subArray1 please see the comment 对于subArray1请参阅评论

    NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName];
   // please make returnExecuteQuery's returned array autorelease if it is not.  
   NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
    [subArray addObjectsFromArray:subArray1];

    [subQuery release]; 
    NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName];
    NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
    [langArray addObjectsFromArray:newArray];
    [columnQuery relese];
    NSMutableArray *tempArray = [[NSMutableArray alloc] init];

    for (int i=0; i<[newArray count]; i++) {
        NSMutableString *tempKey = [[NSMutableString  alloc]initWithFormat:@"%@",lblshortName.text]];


        NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
        [tempKey release];

        if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""] ) {
            NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
            NSMutableString *tempString  = [[NSMutableString alloc] initWithFormat:@"%@ : %@",lblshortName.text, decodedString3]];

            [tempArray addObject:tempString];
            [tempString release];
        }
        else {
            [tempArray addObject:@"<empty>"];
        }

        NSMutableString *detail = nil;

        for (int j=0; j<[lableNameArray count]; j++) 
        {
             detail = [[ NSMutableString alloc]initWithString:@"_________________"];
            NSMutableString *key = [[NSMutableString alloc]initWithFormat:@"%@",[lableNameArray objectAtIndex:j]];
            NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key];
           [key release];

            if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
            {
                NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
                [detail setString:[NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
            } 
              [detailTextArray addObject:detail]; 
              [detail release];              
        }   


    }
    [subArray1 release];
    [newArray release];

UPDATE : Please do read comments in the code and reply back so that things could be improved. UPDATE :请在代码中阅读评论并回复,以便可以改进。

    NSMutableString *subQuery =[ [NSMutableString alloc] initWithFormat:@"SELECT %@ FROM tbl_lang WHERE glossary = '%@'",append1,glossaryName];
   //*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.  
   NSArray *subArray1 = [[self returnExecuteQuery:subQuery] mutableCopy] ;
    [subArray addObjectsFromArray:subArray1];

    [subQuery release]; 
    NSMutableString *columnQuery ==[ [NSMutableString alloc] initWithFormat:@"select AutoID,%@ from tbl_lang where glossary='%@'",lblshortName.text,glossaryName];
    //*****NOTE THIS POINT ----> please make returnExecuteQuery's returned array autorelease if it is not.  
    NSArray *newArray =[[self returnExecuteQuery:columnQuery] mutableCopy] ;
    [langArray addObjectsFromArray:newArray];
    [columnQuery relese];
    NSMutableArray *tempArray = [[NSMutableArray alloc] init];

    for (int i=0; i<[newArray count]; i++) {
        NSMutableString *tempKey = [[NSMutableString  alloc]initWithFormat:@"%@",lblshortName.text]];


        NSString *cellText = [[newArray objectAtIndex:i] valueForKey:tempKey];
        [tempKey release];

        if (cellText != (NSString *)[NSNull null] && ![cellText isEqualToString:@""] ) {
            NSString *decodedString3 = [NSString stringWithUTF8String:[cellText cStringUsingEncoding:[NSString defaultCStringEncoding]]];
            NSMutableString *tempString  = [[NSMutableString alloc] initWithFormat:@"%@ : %@",lblshortName.text, decodedString3]];

            [tempArray addObject:tempString];
            [tempString release];
        }
        else {
            [tempArray addObject:@"<empty>"];
        }

        NSMutableString *detail =  [[ NSMutableString alloc]initWithString:@"_________________"];

        for (int j=0; j<[lableNameArray count]; j++) 
        {

            NSMutableString *key = [[NSMutableString alloc]initWithFormat:@"%@",[lableNameArray objectAtIndex:j]];
            NSString *checkNull=[[subArray1 objectAtIndex:i] valueForKey:key]; //also here if you note you are using subArray1 not subArray?
           [key release];

            if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
            {
                NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
                [detail setString:[NSString stringWithFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]];
               break;//I am not sure why you are checking this condition but assume that you want to get NOT NULL VALUE and  add it to array?
            } 

        }   
        [detailTextArray addObject:detail]; 
        [detail release];              

    }
    [subArray1 release];
    [newArray release];

UPDATE 2: 更新2:

if(checkNull != (NSString *)[NSNull null] && checkNull.length > 0)
            {
                NSString *decodedString4 = [NSString stringWithUTF8String:[checkNull cStringUsingEncoding:[NSString defaultCStringEncoding]]];
                [detail appendFormat:@"%@\n%@ : %@ ",detail,[lableNameArray objectAtIndex:j],decodedString4]];

            }

Thanks, 谢谢,

You could start by releasing your tempArray once done with it (after the loops). 你可以从一旦完成就释放你的tempArray(在循环之后)。

Often, the higher levels leaks are hidden in the flood of lower level ones (ie a container leaking causes all its content to be leaked as well), which might be the case for your string. 通常,较高级别的泄漏隐藏在较低级别的漏洞中(即容器泄漏导致其所有内容也泄漏),这可能是您的字符串的情况。

Using mutableCopy] autorelease]; 使用mutableCopy] autorelease]; is fine by the way. 顺便说一下很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM