繁体   English   中英

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

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

在我的应用程序中,我在NSMutableArray,NSArray和NSString中出现内存泄漏。

这是代码。

    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]; 

    }

当我在仪器中运行时,我发现了泄漏

-subArray1在第二行。

-detail(NSString)在第二个for循环中。

subArray和langArray是我的全局数组。

如果我从NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease];删除mutableCopy NSArray *newArray =[[[self returnExecuteQuery:columnQuery] mutableCopy] autorelease]; NSArray *subArray1 = [[[self returnExecuteQuery:subQuery] mutableCopy] autorelease]; 然后subArray和langArray不保留值。

如何避免此代码中的内存泄漏?

不确定是什么导致内存泄漏,但这可能会有所帮助。 这是一种更直接的复制数组的方法,可能会避免泄漏:

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

这基本上是由returnExecuteQuery返回的数组的一级深层副本。 您可以在“ 集合编程主题”中更详细地阅读它。

我不确定mutableCopy是如何工作的,这可能与泄漏有关。 如果它复制旧数组中的对象然后将它们添加到新数组,它们可能会进入数组,其保留计数为2(副本为1,而数组为1)。很有意义,它应该这样工作。 但是,如果确实如此,那可能是造成泄漏的原因。

请试试这个,在上面的代码中你创建了两个属于自动释放池的对象,这里是我试图处理那些字符串变量释放的一个版本。

其次, detail的泄漏是因为您在代码中多次取消引用它。 对于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 :请在代码中阅读评论并回复,以便可以改进。

    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];

更新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]];

            }

谢谢,

你可以从一旦完成就释放你的tempArray(在循环之后)。

通常,较高级别的泄漏隐藏在较低级别的漏洞中(即容器泄漏导致其所有内容也泄漏),这可能是您的字符串的情况。

使用mutableCopy] autorelease]; 顺便说一下很好。

暂无
暂无

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

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