Не удается освободить память объекта NSData - PullRequest
0 голосов
/ 14 ноября 2009

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

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

Мои настройки компилятора являются стандартными, за одним исключением, я выбираю Objective-C Сборка мусора = требуется

Может быть, кто-то может показать мне, что я делаю не так.

Вот код:

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

2 голосов
/ 14 ноября 2009

Пара вещей:

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

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

NSData* inputData = [NSData dataWithContentsOfFile:filePath];

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

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

Вам обязательно нужно прочитать документ Управление памятью какао . Это многое прояснит.

0 голосов
/ 18 ноября 2009

После прочтения документации по управлению памятью я знал столько же, сколько и раньше. Итак, я начал пробовать и ошибаться. Я пробовал такие вещи, как выпустить NSData Object, пока retaincount будет 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: может быть, кто-то может сказать мне, почему я не смог выпустить его сам или почему там, где счет удержания равен 2.

...