English 中文(简体)
Can t free memory of NSData object
原标题:

i m new to xcode / cocoa and even objective-c thus my question might be stupid. Im trying to write a program that will hash files in a folder. I looked around and found a way to load a file via a NSData object and than hash it s bytes with CC_SHA512.

If i try to hash a few more files i noticed my memory running out. Using the Run -> Performance Tools i could pinpoint my problem. All NSData Objects i created are still in memory. I tryed autorelease and manualy release with release / dealloc. Nothing is working.

My Compiler Settings are standard with one exception i choose Objective-C Garbage Collection = required.

Maybe someone can show me what i m doing wrong.

Here is the code:

-(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("
:%s:
",[file UTF8String]);
            count++;
        }


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

All of this is started by

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

}

Maybe someone has an idea.

Than You in advance :) Nubus

问题回答

A couple of things:

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

You must retain this if you want to keep it around past the current method execution (this is a bit oversimplified, but reasonable for your example). Since dataWithContentsOfFile: doesn t contain alloc, copy, or new you re not responsible for releasing it unless you explicitly retain it. Given that you re only using it locally in the function, you don t need to retain this. Thus, just use the following and don t call release/autorelease or dealloc on it:

NSData* inputData = [NSData dataWithContentsOfFile:filePath];

Further, you never manually dealloc things. Just release/autorelease them as needed. dealloc will get called as required.

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

You definitely need to read the Cocoa Memory Management document. It will clear up a lot.

After reading the MemoryManagement Documentation i knew as much as before. So i started try and error. I tried things like release the NSData Object til the retaincount is 0.. and and and. Than i found a working solution.

I had to init the NSData Object myself, and set it to auto release (i was not able to release it myself because after i called init there was a retaincound of 2 and trying to release it 2 times leads to a crash

blabla here my solution:

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

I hope this will help someone :)

Thank you for your answers.

ps: maybe soneone can tell me why i couldn t release it myself or why there where a retain count of 2.





相关问题
How to change out-of-focus text selection color in Xcode?

Okay, I ll bite. I ve got really pleasant code/window colors set up in Xcode. Ordinarily, my selection color is very visible. When I am doing a project search and iterating through the results, ...

Iphone NSTimer Issue

Hi I am new to objective c. I am trying to make an app for iphone. I have a button on my view, and the click on which the function playSound is called. This is working properly. It does plays the ...

Include a .txt file in a .h in C++?

I have a number of places where I need to re-use some template code. Many classes need these items In a .h could I do something like: #include <xxx.txt> and place all of this code in the ....

Iterating over string/strlen with umlauted characters

This is a follow-up to my previous question . I succeeded in implementing the algorithm for checking umlauted characters. The next problem comes from iterating over all characters in a string. I do ...

Xcode open two editor windows with same file

Is it possible to open the same file in two separate windows in Xcode. I can open a file in one window and the same file in the main Xcode editor window, but I wanted two separate fulltime editor ...

Forcing code signing refresh in Xcode

In our environment, we share resources across multiple projects and platforms. When building for iPhone, only a subset of those resources are needed. Since that subset is still considerable, we have ...

热门标签