Objective-c内存管理
作为Objective-c及其内存管理技术的新手,比较以下两个方面。(原始代码摘自apple.com)Objective-c内存管理,objective-c,memory-management,Objective C,Memory Management,作为Objective-c及其内存管理技术的新手,比较以下两个方面。(原始代码摘自apple.com) 问题: 1.这两件作品的效果相同吗? 2.这两个部分是否实现了相同的内存管理结果?(关于内存清理、泄漏等) 3.就最佳实践而言,以下第二条代码是否违反了任何规定?表演 void main() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSArray *args = [[NSProcessInfo
问题:
1.这两件作品的效果相同吗?
2.这两个部分是否实现了相同的内存管理结果?(关于内存清理、泄漏等)
3.就最佳实践而言,以下第二条代码是否违反了任何规定?表演
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
for (NSString *fileName in args) {
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSError *error = nil;
NSString *fileContents = [[[NSString alloc] initWithContentsOfFile:fileName
encoding:NSUTF8StringEncoding error:&error] autorelease];
/* Process the string, creating and autoreleasing more objects. */
[loopPool drain];
}
/* Do whatever cleanup is needed. */
[pool drain];
exit (EXIT_SUCCESS);
}
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
NSString *fileContents = [[NSString alloc] autorelease];
for (NSString *fileName in args)
{
// NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSError *error = nil;
fileContents = [fileContents initWithContentsOfFile:fileName encoding:NSUTF8StringEncoding error:&error];
/* Process the string, creating and autoreleasing more objects. */
//[loopPool drain];
}
/* Do whatever cleanup is needed. */
[pool drain];
exit (EXIT_SUCCESS);
}
fileContents=[fileContents…
时,它肯定会爆炸和/或泄漏。实现假定其实例的内存为零,因为这是由运行时保证的
即使一个初始值设定项被证明可以正常工作,也不会出现问题或泄漏,但许多初始值设定项不会
不要像这样“更新”你的对象-请按正常方式进行=)
序列(在非gc环境中)应为:1)alloc
2)init…
(使用指定的初始值设定项)3)dealloc
这两个部分是否实现了相同的内存管理结果?(内存清理、泄漏等)
不可以。除了#1中概述的内容外,您不应该假设从alloc
返回的地址将与从初始值设定项返回的地址相同。初始值设定项可以选择销毁alloc
的结果并创建或返回另一个分配。在这种情况下,您将引入引用计数不平衡(效果:泄漏和/或僵尸)
就最佳实践而言,以下第二条代码是否违反了任何规定
NSString*fileContents=[[NSString alloc]autorelease];
很奇怪,非常不传统。第一次读它时,我错过了错误,因为将init…]
放在alloc
和autorelease
之间太常规了
就性能而言,以下第二条代码是否违反了任何规定
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
for (NSString *fileName in args) {
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSError *error = nil;
NSString *fileContents = [[[NSString alloc] initWithContentsOfFile:fileName
encoding:NSUTF8StringEncoding error:&error] autorelease];
/* Process the string, creating and autoreleasing more objects. */
[loopPool drain];
}
/* Do whatever cleanup is needed. */
[pool drain];
exit (EXIT_SUCCESS);
}
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
NSString *fileContents = [[NSString alloc] autorelease];
for (NSString *fileName in args)
{
// NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSError *error = nil;
fileContents = [fileContents initWithContentsOfFile:fileName encoding:NSUTF8StringEncoding error:&error];
/* Process the string, creating and autoreleasing more objects. */
//[loopPool drain];
}
/* Do whatever cleanup is needed. */
[pool drain];
exit (EXIT_SUCCESS);
}
从内部循环中删除自动释放池可能会影响性能。当发生大分配和/或高迭代时,最好创建小型本地化池,如原始池。要回答您的问题: 1) 这两件作品能达到同样的效果吗 不,他们没有,主要是因为第二个例子不正确,有两个原因
NSString*fileContents=[[NSString alloc]autorelease]
没有什么意义。这一行基本上为字符串分配空间,甚至不初始化它(并将其初始保留计数增加到1),告诉它将自己放入自动释放池。这是一个大禁忌fileContents=[fileContents initWithContentsOfFile:fileName编码:NSUTF8StringEncoding错误:&error]
也没有什么意义。您正在使用未以任何方式释放或重置的旧内存初始化新对象,这只是未定义的行为。正如Sherm Pendley所提到的,您不能一次性分配空间,而只是毫无顾虑地重用该内存,而且由于您不知道NSString
是如何在内部定义的,这可能会导致内存泄漏,或者非常简单地在您面前爆炸。又一个大禁忌+alloc
和-init
几乎总是相互配对,但这不仅仅是因为惯例,而是因为这种配对是正确的。在开始使用内存之前,必须+alloc
内存,并且必须-init
将内存归零,并使其处于正确的状态才能正常运行。任何其他组合都可能不适合使用
2) 这两个部分是否实现了相同的内存管理结果?(关于内存清理、泄漏等)
不,他们绝对不会。第二个将泄漏大量内存,甚至可能无法运行。第一次当然可以,但由于使用内部自动释放池,可能无法有效运行
3) 就最佳实践而言,以下第二条代码是否违反了任何规定?表演
是的,确实如此,事实上,即使是第一个也可能无法有效运行。创建内部自动释放池可能不符合您的最佳利益,甚至可能会妨碍您的程序。这位尊者用自动释放池做了一些测试,结果有点令人惊讶。事实证明,不同大小的自动释放池在不同的计算机上工作得更好(当时,在他的旧计算机上,每个池中100个对象是最有效的;对我来说,10000个对象工作得稍微好一点,甚至只比1000个对象稍微好一点)第二个显然是非传统的,而且很可能是错误的;分配一块内存,使用该内存初始化一个对象,将内存标记为释放,然后再次使用它初始化一个新对象,在重新标记的过程中。@Josh,不是这样,他所做的很好。除了变量之外,没有任何东西可以重用,它只是在每次迭代中指向不同的内存位置。我在第二部分中放置文件内容的“自动释放”时出错。我编辑了代码以反映更改。第二个示例仍然不正确-不能使用
+alloc
创建一个对象,然后重复调用其-init
方法之一。每次都必须成对调用+alloc
和-init…
。正如Sherm所说,第二个示例完全不正确。这种模式毫无意义。也没有任何理由编写[[[NSString alloc]init]autorelease]
——这只是一个空的、不可变的字符串,所以您最好使用@“
。