xcode 无法释放 NSData 对象的内存
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1735201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can't free memory of NSData object
提问by TheNubus
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.
我是 xcode/cocoa 甚至 Objective-c 的新手,因此我的问题可能很愚蠢。我正在尝试编写一个程序来散列文件夹中的文件。我环顾四周,找到了一种通过 NSData 对象加载文件的方法,而不是用 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.
如果我尝试散列更多文件,我注意到我的内存不足。使用 Run -> Performance Tools 我可以查明我的问题。我创建的所有 NSData 对象仍在内存中。我尝试使用 release / dealloc 进行自动释放和手动释放。没有任何工作。
My Compiler Settings are standard with one exception i choose Objective-C Garbage Collection = required.
我的编译器设置是标准的,但有一个例外,我选择了 Objective-C 垃圾收集 = 必需。
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
比你提前:) Nubus
回答by nall
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:
如果您想在当前方法执行之后保留它,则必须保留它(这有点过于简化,但对您的示例来说是合理的)。由于dataWithContentsOfFile:
不包含 alloc、copy 或 new,除非您明确保留它,否则您不负责释放它。鉴于您仅在函数中本地使用它,您不需要保留它。因此,只需使用以下内容,不要在其上调用 release/autorelease 或 dealloc:
NSData* inputData = [NSData dataWithContentsOfFile:filePath];
Further, you never manually dealloc things. Just release/autorelease them as needed. dealloc will get called as required.
此外,您永远不会手动解除分配事物。只需根据需要释放/自动释放它们。dealloc 将根据需要被调用。
[inputData dealloc]; // don't do this explicitly
You definitely need to read the Cocoa Memory Management document. It will clear up a lot.
您肯定需要阅读Cocoa 内存管理文档。它会清除很多。
回答by TheNubus
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.
阅读 MemoryManagement 文档后,我知道的和以前一样多。所以我开始尝试和错误。我尝试了诸如释放 NSData 对象直到保留计数为 0.. 和和和。比我找到了一个有效的解决方案。
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
我必须自己初始化 NSData 对象,并将其设置为自动释放(我无法自己释放它,因为在我调用 init 后,保留值为 2 并尝试释放它 2 次导致崩溃
blabla here my solution:
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;
}
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.
ps:也许有人可以告诉我为什么我不能自己释放它或者为什么保留计数为 2。