2013-11-22 1 views
0

객관적 c에 익숙하지 않아 어리석은 질문 인 경우 용서해주십시오. 디렉토리에있는 파일 목록을 파싱하는 배경 스레드를 만들었습니다. 디렉토리의 파일은 언제든지 바뀔 수 있습니다.iOS - contentsOfDirectoryAtPath를 호출하면 루프에서 메모리가 누수됩니다.

루프의 반복마다 "contentsOfDirectoryAtPath"를 호출하고 갑자기 300MB 이상 할당됩니다. ARC에서 반환 된 배열을 해제하는 방법을 알 수 없습니다. 누군가가 나를 올바른 방향으로 향하게 할 수 있습니까?

-(void) offlineModeThread 
{ 

    NSString *dataDir = [ViewController getDataDirectory]; 
    NSFileManager *nfm = [NSFileManager defaultManager]; 

    while(1) 
    { 
     NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil]; 
     /* 
     if(files == nil) 
      break; 

     if([files count] <= 0) 
     { 
      files = nil; 
      [NSThread sleepForTimeInterval: 5.0f]; 
      continue; 
     } 

     if(![ViewController obtainLock]) 
     { 
      files = nil; 
      continue; 
     } 
     */ 
     //[ViewController releaseLock]; 
     files = nil; 
    } 

} 

'파일'을 nil로 설정하여 배열을 릴리스하려고 시도했지만 작동하지 않습니다.

+0

ARC 프로젝트를 사용합니까? – Joey

+0

참고 사항 : [NSFileManager defaultManager]는 스레드로부터 안전하지 않으므로 대신 [[NSFileManager alloc] init]을 사용하십시오. – San

+0

@ 샌프란 [설명서] (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsfilemanager_Class/Reference/Reference.html#//apple_ref/doc/uid)를 읽었을 것입니다./20000305-SW19)와 같은 주장을하기 전에. – CodaFi

답변

1

어떻게이 스레드를 만드시겠습니까? NSThread? NSOperation 및 NSOperationQueue? GCD?

NSThread 및 NSOperation의 경우 스레드 설정의 일부로 자체 자동 풀을 생성해야합니다. 그렇게하면 임시 개체가 해당 스레드 내에서 올바르게 관리됩니다.

나는 GCD가 당신을 위해이 세부 사항을 처리한다고 생각합니다. 목표 C의 최신 버전에서

임시 객체의 톤을 생성 루프에 대한 새로운 구문

@autoreleasepool 
{ 
    //Code to use a local autorelease pool 
} 

를 사용해야합니다 (C 2.0 목적, 저는 믿습니다), 당신은 어떤을위한 지역 오토 릴리즈 풀을 만들 수 있습니다 코드 블록 이 같은 코드를 리팩토링 수 있습니다 : (. 따라서 그 반복에서 생성 된 모든 임시 개체를 해제)는 루프의 각 반복에 대한 새로운 오토 릴리즈 풀을 생성하고, 마지막에 드레인 원인이

while(1) 
{ 
    @autoreleasepool 
    { 
    NSArray *files = [nfm contentsOfDirectoryAtPath:dataDir error:nil]; 
    /* 
    if(files == nil) 
     break; 

    if([files count] <= 0) 
    { 
     files = nil; 
     [NSThread sleepForTimeInterval: 5.0f]; 
     continue; 
    } 

    if(![ViewController obtainLock]) 
    { 
     files = nil; 
     continue; 
    } 
    */ 
    //[ViewController releaseLock]; 
    files = nil; 
    } 
} 

그런데 NSThread를 사용하는 경우에는 사용하지 마십시오. 대신 GCD 사용 방법을 배우십시오. GCD (Grand Central Dispatch)는 NSThread보다 시스템 리소스를 훨씬 효율적으로 사용합니다. NSThread는 POSIX 스레드를 기반으로합니다. POSIX 스레드는 매우 비싸고 응용 프로그램 수명 동안 장치의 실제 메모리를 묶습니다.

NSOperationQueues는 최근 OS 버전에서 GCD를 사용하기 위해 리팩토링되었으므로 대부분 내부적으로 GCD보다 사용하기가 더 어렵지 만 내부적으로도 효율적입니다.

+0

이 답변을 주셔서 감사합니다. 자동 풀 풀을 추가하면 트릭을 수행하게됩니다. NSThread를 사용하여이 스레드를 만들고 있습니다. 당신은 응용 프로그램의 수명 동안 NSThread가 실제 메모리를 사용한다고 말했지만이 스레드가 응용 프로그램의 수명 동안 실행되어야한다면 정말 중요합니까? 두 경우 모두 GCD를 살펴볼 것입니다 - 포인터를 주셔서 감사합니다! – Gogeta70

0

글쎄, 나는 그 대답이 분명하다고 생각한다. documentation을 살펴보십시오.

많은 프로그램이 자동 릴리즈되는 임시 객체를 만듭니다. 이 개체는 블록의 끝까지 프로그램의 메모리 사용 공간을 추가합니다. 많은 경우, 현재 이벤트 루프 반복이 끝날 때까지 임시 객체가 으로 누적되도록 허용하여 과도한 오버 헤드가 이되지 않도록합니다. 그러나 경우에 따라 임시 개체를 많이 생성하여 메모리가 실질적으로 추가 메모리 인 이고 더 빨리 처리 할 수 ​​있습니다. 이 후자의 경우 자신의 자동 복구 풀 블록을 만들 수 있습니다. 블록의 끝 부분 인 에서 임시 개체가 해제됩니다. 일반적으로 은 할당 해제를 초래하므로 프로그램 메모리의 메모리 크기는 입니다.

그리고이 부분은 question입니다.

많은 임시 개체를 생성하므로 솔루션에 @autoreleasepool{}이 사용됩니다.

관련 문제