簡體   English   中英

NSThread導致iPhone中的內存泄漏

[英]NSThread Causing memory Leaks in iPhone

我在后台線程中明智地上傳圖像,每個塊的大小為512kb,據我所知,我已經使用release,nsautoreleasepool來處理內存泄漏問題。 以下是分塊上傳圖像的代碼。

- (void)FetchDataFromDB : (NSNumber *) isOffline
{
 @autoreleasepool {
    @try {
    NSLog(@"FetchDatafromDB");
    isThreadStarted = YES;

    VYukaDBFunctions *vdb = [VYukaDBFunctions getInstance];

    NSMutableArray *fileNames = [vdb GetFileNames:[isOffline integerValue]];
    for(int j=0 ; j<[fileNames count] ; j++)
    {

        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSString * filename = fileNames [j] ;
        int _outgoingMsgId = [[vdb SelectMsgId:filename] intValue];
        int  _totalchunk =[[vdb SelectTotalChunk:filename]intValue];
        int currentChunk = [vdb GetCurrentChunk:filename];
    for( int i=currentChunk ; i <= _totalchunk ; i++)
    {

        NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];

        NSString *AsyncRequest = [[NSString alloc] init];
        AsyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId];

        if(![AsyncRequest isEqual:@""])
        {

        BOOL status = [self UploadChunkWise :AsyncRequest : 1 : i : vdb : filename : _outgoingMsgId];
      // AsyncRequest = NULL;
     //  [AsyncRequest release];
        if(status){
            if(i==_totalchunk)
            {
                NSLog(@"Deleting from medialist , FileName :%@", filename);
                [vdb DeleteFromMediaList : filename];

            }
        }
        else{

            [vdb DeleteFromMediaList : filename];
            break;
        }
        }

        [innerPool drain];
    }

        [pool drain];
    }

    [fileNames removeAllObjects];

   // [fileNames release];

    //recurssive call to check any pending uploads..
    if([[vdb GetFileNames:[isOffline integerValue]] count] > 0)
    {
        NSLog(@"Calling Recursively..");
        [self FetchDataFromDB:[isOffline integerValue]];
    }

    }
    @catch (NSException *exception) {

        NSLog(@"Exception caught on Uploading from FetchDataFromDB:%@", exception);

    }
    @finally {

    }
}

 NSLog(@"thread quit ");
 isThreadStarted = NO;
[NSThread exit];

}

-(BOOL) UploadChunkWise :(NSString *) AsyncRequest : (int) count : (int)currentChunk : (VYukaDBFunctions * ) vdb : (NSString *) currentFileName : (int) outgoingMsgId
{

NSHTTPURLResponse *response ;
NSError *error;
//Yes, http
NSMutableURLRequest *httpRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL     URLWithString:@"Url goes here"]];
NSData* data = [AsyncRequest dataUsingEncoding:NSUTF8StringEncoding];

[httpRequest setHTTPMethod:@"POST"];
[httpRequest setHTTPBody:data];

[httpRequest setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
NSData *returnedData = [NSURLConnection sendSynchronousRequest: httpRequest returningResponse:&response error:&error] ;
NSString *result= [[NSString alloc] initWithData:returnedData encoding:NSASCIIStringEncoding];
[httpRequest release];

returnedData= NULL;
[returnedData release];
data = NULL;
[data release];

if ([result rangeOfString:@"success"].location != NSNotFound )
{
    NSLog(@" success");
    [vdb DeleteCurrentChunkFromOutgoingTable:currentChunk : outgoingMsgId];
    [result release];
    return YES ;

}
else if ([result rangeOfString:@"fail"].location != NSNotFound )
{
    [result release];
    if (count < 3) {

        return  [self UploadChunkWise :AsyncRequest : count+1 : currentChunk: vdb : currentFileName : outgoingMsgId ];
    }
    else
    {
        NSLog(@" failed");
        [vdb DeleteAllCurrentFileChunksFromOutgoingTable:currentFileName];
        return NO ;
    }

}

return NO;

}

我正在如下啟動線程

 [NSThread detachNewThreadSelector:@selector(FetchDataFromDB:) toTarget:self withObject:[NSNumber numberWithInt:0]];

問題是上傳9到12個塊后,出現內存錯誤。 我收到4到5次內存警告,然后該應用程序崩潰。在控制台中,我首先在應用程序委托類上獲取內存警告,然后是4個擴展UIViewController的類。 為什么我在應用程序委托和其他類型為UIViewController的類上收到警告。如果單獨的線程給我內存錯誤,為什么我必須釋放其他類的對象? 我在這里做錯了什么? 我無法使用ARC,因為我已將其與不使用ARC的舊代碼集成在一起,因此我嘗試了明智地啟用ARC類,但是這樣做並不起作用。 誰能幫助我找出這段代碼中是否有內存泄漏。 歡迎提出建議並表示贊賞。

兩件事-首先,我看到了這一點:

NSString *AsyncRequest = [[NSString alloc] init];
AsyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId];

這應該合並為:

NSString *asyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId];

相反,您正在創建一個新實例,然后立即生成或引用另一個實例。

第二:

您的代碼很難閱讀,並且不遵循Objective-C smalltalk約定。

變量名稱應以lowercase字母開頭。 方法名稱還應該以小寫字母開頭。 類名和功能應以大寫字母開頭。 由於我和許多其他人已經受過訓練,可以看到大寫字母並認為“類別名稱”而不是“可能的變量名稱”,因此很難閱讀。 僅供參考

最后,您的某些方法采用多個參數,例如上面的參數。 您確實應該為每個參數添加一個前綴,以便於理解該參數的用途。 這個:

[vdb SelectAsyncRequest: PARAMETER : PARAMETER];

如果是,它將看起來更好:

[vdb selectAsyncRequestForParameter: PARAMETER withOtherParameter:OTHERPARAM];

編輯:我也不認為您需要那么多自動發布池。 整個內容已經包裝在一個大型自動釋放池中。

EDIT2:我還看到了很多不必要的release調用。 在您的UploadChunkWise方法中,您要對*data*returnedData調用release,它們已經隱式自動釋放 將對象返回給您的方法將已經擁有所有權並“移交給”您。 本質上,這些方法可以做到這一點:

NSData *data = [[NSData alloc] init];
return [data autorelease];

當您獲取它時,如果要保留它,則必須自己retain它,否則它將在方法返回時銷毀。

但是,對使用-init創建的NSString *result實例調用release是正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM