2009-11-14 4 views
0

Я новичок в xcode/какао и даже объективе-c, поэтому мой вопрос может быть глупым. Я пытаюсь написать программу, которая будет хэш-файлами в папке. Я огляделся и нашел способ загрузить файл через объект NSData, а не hash - это байты с CC_SHA512.Невозможно освободить память объекта NSData

Если я попытаюсь записать еще несколько файлов, я заметил, что моя память заканчивается. Используя Run -> Performance Tools, я мог бы определить свою проблему. Все объекты NSData, которые я создал, все еще находятся в памяти. Я попробовал автозапуск и ручную версию с релизом/dealloc. Ничего не работает.

Мои настройки компилятора являются стандартными с одним исключением, я выбираю Objective-C Garbage Collection = required.

Возможно, кто-то может показать мне, что я делаю неправильно.

Вот код:

-(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; 
} 

Все это начинается с

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

} 

Может быть кто-то есть идея.

, чем вы заранее :) Nubus

ответ

2

Пара вещей:

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

Вы должны сохранить это, если вы хотите сохранить его вокруг после текущего выполнения метода (это немного упрощен , но разумно для вашего примера). Поскольку dataWithContentsOfFile: не содержит alloc, copy или new, вы не отвечаете за его освобождение, если вы явно не сохранили его. Учитывая, что вы используете его только локально в функции, вам не нужно сохранять это. Таким образом, только с помощью следующего и не Отбоя вызова/autorelease или dealloc на нем:

NSData* inputData = [NSData dataWithContentsOfFile:filePath]; 

Кроме того, вы никогда не вручную dealloc вещей. Просто отпустите/авторизируйте их по мере необходимости. dealloc будет вызван по мере необходимости.

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

Вам обязательно нужно прочитать Cocoa Memory Management document. Это прояснит многое.

+0

Hi, спасибо за ссылку. Документация гласит, что, если я использую удобные методы, мне не нужно использовать выпуск, как вы сказали. Объект NSData не используется вне функции hashFileByName. Я действительно не знаю, как избавиться от объектов NSData. (Я не прохожу через блок документации) Есть ли способ принудительно удалить такой объект? Спасибо – TheNubus

+0

Способы удобства дают вам автореализованный объект. Это означает, что (при условии, что его значение удержания равно нулю), оно будет восстановлено в памяти в следующей точке сбора авторезинки. Если вы хотите более подробно говорить об этом, вам нужно выделить/init/release. – nall

0

После прочтения документации по управлению памятью я знал столько же, сколько и раньше. Поэтому я начал попытки и ошибку. Я пробовал такие вещи, как освобождение объекта NSData до тех пор, пока скилл будет 0 .. и и и. Затем я нашел рабочее решение.

Мне пришлось сначала инициализировать объект NSData и установить его для автоматического выпуска (я не смог его освободить сам, потому что после того, как я назвал init, было удержано 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;  
} 

Я надеюсь, что это поможет кому-то :)

Спасибо за ваши ответы.

ps: может быть, soneone может сказать мне, почему я не мог освободить его сам или почему там, где удержание счета составляет 2.

Смежные вопросы