2009-11-14 1 views
0

저는 xcode/cocoa와 심지어 objective-c에 익숙하기 때문에 제 질문은 어리 석을 수 있습니다. 임 폴더에 파일을 해시하는 프로그램을 작성하려고합니다. 주위를 둘러 보았고 NSData 객체를 통해 파일을로드하는 방법을 발견했으며 해시보다 CC_SHA512를 사용하여 바이트를 가져 왔습니다.NSData 객체의 메모리를 비울 수 없습니다.

내가 더 많은 파일을 해시하려고하면 메모리가 부족하다는 것을 알았습니다. 실행 -> 성능 도구를 사용하여 내 문제를 정확하게 지적 할 수 있습니다. 내가 만든 모든 NSData 객체는 여전히 메모리에 있습니다. release/dealloc을 사용하여 autorelease 및 manualy 릴리스를 시도했습니다. 아무것도 작동하지 않습니다.

내 컴파일러 설정은 Objective-C 가비지 수집 = 필수를 선택한 한 가지 예외를 제외하고는 표준입니다.

누군가 내가 잘못하고있는 것을 나에게 보여줄 수 있습니다. 이 모든

int main(int argc, char *argv[]) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    //return NSApplicationMain(argc, (const char **) argv); 
    MemoryLeakTest *test = [[[MemoryLeakTest alloc]init]autorelease]; 
    [test hashFilesInDirectory:@"/huge directory/" :YES :nil :nil]; 
    [pool drain]; 
    [pool release]; 
    [pool dealloc]; 

} 

어쩌면 누군가가 아이디어를 가지고 시작한다

-(FileHash*) hashFileByName :(NSString*) filePath{ 

    //NSData* inputData = [inputStr dataUsingEncoding:NSUTF8StringEncoding]; 
    NSLog(filePath); 
    NSData* inputData = [[NSData dataWithContentsOfFile:filePath] autorelease]; 
    unsigned char outputData[CC_SHA512_DIGEST_LENGTH]; 
    CC_SHA512([inputData bytes], [inputData length], outputData); 


    NSMutableString* hashStr = [NSMutableString string]; 
    int i = 0; 
    for (i = 0; i < CC_SHA512_DIGEST_LENGTH; ++i) 
     [hashStr appendFormat:@"%02x", outputData[i]]; 


    //NSLog(@"%@ hash : %@",filePath,hashStr); 

    FileHash *hash = [[[FileHash alloc]init]autorelease]; 
    [hash setFileHash:hashStr]; 
    [hash setFilePath:filePath]; 
    [inputdata release]; 
    [inputdata dealloc]; 
    return hash;  
} 

-(NSMutableArray*) hashFilesInDirectory:(NSString*) pathToDirectory:(Boolean) recursive : (IBOutlet id) Status : (Boolean*) BreakOperation{ 

    NSGarbageCollector *collect = [NSGarbageCollector defaultCollector]; 

    NSMutableArray *files; 
     files = [[self listFilesOnlyRecursive:pathToDirectory] autorelease]; 

    NSMutableArray *hashes = [[[NSMutableArray alloc]init]autorelease]; 

    for (NSString *file in files) { 

     [hashes addObject: [self hashFileByName:file]]; 
     [collect collectExhaustively]; 
    } 


    return hashes; 
} 

-(NSMutableArray*) listFilesOnlyRecursive : (NSString*) startDir { 

    NSMutableArray *filelist = [[[NSMutableArray alloc] init]autorelease]; 

    //Inhalt eines Verzeichnisses auflisten (unterverzeichnisse werden ignoriert 
    NSFileManager *manager = [[NSFileManager defaultManager]autorelease]; 

    NSDirectoryEnumerator *enumerator = [manager enumeratorAtPath:startDir]; 
    int count = 0; 
    id file; 
    while (file = [enumerator nextObject]) 
    { 

     //  file = [[[[startDir stringByAppendingString:@"/"]autorelease] stringByAppendingString:file] autorelease 
     //    ]; 
     file = [NSString stringWithFormat:@"%@/%@",startDir,file]; 
     BOOL isDirectory=NO; 
     [[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory]; 
     if (!isDirectory){ 
      [filelist addObject:file]; 
      //printf("\n:%s:\n",[file UTF8String]); 
      count++; 
     } 


    } 
    NSLog(@"Es waren %i files",count); 
    return filelist; 
} 

: 여기

는 코드입니다.

사전에보다

: 은 Nubus

답변

2

몇 가지 : 당신이 조금 과도하게 단순화이다 (현재 메소드 실행지나 주위를 유지하려면

NSData* inputData = [[NSData dataWithContentsOfFile:filePath] autorelease]; 

당신은이를 유지해야한다 , 그러나 당신의보기를 위해 적당한). dataWithContentsOfFile:에는 alloc, copy 또는 new가 포함되어 있지 않으므로 명시 적으로 보유하지 않는 한 해제 할 책임이 없습니다. 함수에서 로컬에서만 사용한다는 점을 감안할 때이를 유지할 필요가 없습니다. 따라서, 그냥에서 다음과 호출하지 않습니다 릴리스/오토 릴리즈 또는 할당 해제를 사용

NSData* inputData = [NSData dataWithContentsOfFile:filePath]; 

또한, 수동으로 일을 할당 해제하지 않습니다. 필요에 따라 릴리스/자동 해제하십시오. dealloc은 필요에 따라 호출됩니다.

[inputData dealloc]; // don't do this explicitly 

확실히 Cocoa Memory Management document을 읽을 필요가 있습니다. 그것은 많은 것을 정리할 것입니다.

+0

안녕하세요, 링크를 이용해 주셔서 감사합니다. 설명서에는 편의 방법을 사용하는 경우 사용자가 말한 것처럼 릴리스를 사용할 필요가 없다고 명시되어 있습니다. NSData 객체가 hashFileByName 함수 외부에서 사용되지 않습니다. NSData 객체를 제거하는 방법을 알지 못합니다. (나는 문서 제트기를 사용하지 않습니다.) 그런 물체를 강제로 제거 할 수있는 방법이 있습니까? 감사합니다 – TheNubus

+0

편리한 방법을 사용하면 자동 렌더링 된 객체를 다시 사용할 수 있습니다. 즉, 보유 개수가 0이라고 가정하면 다음 자동 회수 수집 시점에 메모리에 회수됩니다. 좀 더 명확히하고 싶다면/init/release를 할당해야합니다. – nall

0

MemoryManagement 문서를 읽은 후에도 이전만큼 많이 알고있었습니다. 그래서 나는 착오를 시작했다. 나는 retainCount가 0 일 때까지 NSData 객체를 릴리스하는 것과 같은 것을 시도했다. and and and. 나는 일하는 해결책을 찾았습니다.

NSData 객체를 직접 초기화해야하고 자동 릴리즈로 설정해야합니다. init 호출 후 retaincound가 2이고이를 2 회 릴리스하려고 시도하면 충돌이 발생하기 때문에 직접 풀어 낼 수 없었습니다.

-(FileHash*) hashFileByName :(NSString*) filePath{ 

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

    //NSData* inputData = [inputStr dataUsingEncoding:NSUTF8StringEncoding]; 
    NSData* inputData = [[[NSData alloc]initWithContentsOfFile:filePath] autorelease]; 
    unsigned char outputData[CC_SHA512_DIGEST_LENGTH]; 
    CC_SHA512([inputData bytes], [inputData length], outputData); 


    NSMutableString* hashStr = [NSMutableString string]; 
    int i = 0; 
    for (i = 0; i < CC_SHA512_DIGEST_LENGTH; ++i) 
     [hashStr appendFormat:@"%02x", outputData[i]]; 



    [innerpool drain]; 

    //NSLog(@"%@ hash : %@",filePath,hashStr); 

    FileHash *hash = [[[FileHash alloc]init]autorelease]; 
    [hash setFileHash:hashStr]; 
    [hash setFilePath:filePath]; 

    return hash;  
} 

내가이 사람 :)

귀하의 답변을 주셔서 감사합니다 도움이되기를 바랍니다 : 내 솔루션 여기

blabla.

ps : 어쩌면 내가 왜 나 자신을 풀 수 없는지 또는 왜 2를 유지하는지 알 수 있습니다.