Objective-c内存管理

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

作为Objective-c及其内存管理技术的新手,比较以下两个方面。(原始代码摘自apple.com)
问题:
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]
    ——这只是一个空的、不可变的字符串,所以您最好使用
    @“