无法释放 NSData 对象的内存

发布于 2024-08-11 08:00:05 字数 3185 浏览 4 评论 0原文

我是 xcode / cocoa 甚至 Objective-c 的新手,因此我的问题可能很愚蠢。我正在尝试编写一个程序来对文件夹中的文件进行哈希处理。我环顾四周,找到了一种通过 NSData 对象加载文件并使用 CC_SHA512 对其字节进行哈希处理的方法。

如果我尝试散列更多文件,我注意到我的内存耗尽了。使用运行->性能工具我可以查明我的问题。我创建的所有 NSData 对象仍在内存中。我尝试使用release/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];

}

也许有人有一个想法开始的。

比你提前:) 努布斯

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("\n:%s:\n",[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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

茶花眉 2024-08-18 08:00:05

有几件事:

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

如果您想将其保留在当前方法执行之后,则必须保留它(这有点过于简单,但对于您的示例来说是合理的)。由于 dataWithContentsOfFile: 不包含 alloc、copy 或 new,因此除非您明确保留它,否则您不负责释放它。鉴于您仅在函数中本地使用它,因此不需要保留它。因此,只需使用以下内容,不要对其调用release/autorelease或dealloc:

NSData* inputData = [NSData dataWithContentsOfFile:filePath];

此外,您永远不会手动dealloc事物。只需根据需要释放/自动释放它们即可。 dealloc 将根据需要被调用。

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

你绝对需要阅读 Cocoa 内存管理文档。就会清楚很多。

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.

来世叙缘 2024-08-18 08:00:05

阅读内存管理文档后,我的了解和以前一样多。所以我开始尝试和错误。我尝试了诸如释放 NSData 对象直到保留计数为 0.. 以及和以及之类的操作。比我找到了一个可行的解决方案。

我必须自己初始化 NSData 对象,并将其设置为自动释放(我无法自己释放它,因为在我调用 init 之后,retaincound 为 2 并且尝试释放它 2 次会导致崩溃

blabla 这里是我的解决方案:

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文