【问题标题】:Need clarification in iPhone memory managementiPhone内存管理需要澄清
【发布时间】:2011-06-27 18:57:36
【问题描述】:

我需要对 iPhone 内存管理进行一些说明。

这里是设置器的示例;
1).

-(void)setValue:(NSString*)input{
[value autorelease];
value = [input retain];
}

在这个例子中,为什么我们必须使用自动释放? 我们可以像下面这样使用吗?


if(value)
[value release];
value = [input retain];

在第一个例子中,为什么我们不应该释放input的内存
2)。 如果我使用以下语句; value 的保留计数是多少

NSString *value;
value = @"welcome";

在上述声明之后,我只是想再设置一个值。那么会发生什么呢?

eg:
value = @"For testing";

3)。 2) 和 3) 有什么区别?

NSString *value;
value = [input1 retain];
...
...
value = [input2 retain];// Now what is the retain count for value

4)。 如果我使用以下语句,为什么应用程序会崩溃?


NSString *value = [[[NSString alloc] init] autorelease];
...
...

提前谢谢..

【问题讨论】:

    标签: ios memory-management autorelease


    【解决方案1】:

    如果“input”与“value”是完全相同的对象,那么调用 [value release] 可以释放对象。所以你必须保留新的输入值,释放旧值,然后将新值赋给 ivar:

    [input retain];
    [value release];
    value = input;
    

    在 2) 和 3) 之后,NSString *value 指向一个字面量的 NSString 对象,在每种情况下,保留计数都是 1,释放它可能不是一个好主意

    这段代码之后:

    value = [input2 retain];
    

    value 是 input2 对象的别名。要意识到的是,对象有保留计数,变量没有。

    至于你的最后一个案例,

    NSString *value = [[[NSString alloc] init] autorelease];
    

    它会创建一个自动释放的空字符串。如果您在自动释放实际发生后再次引用该对象,则可能会发生崩溃,因为您将引用一个不再存在的对象。

    【讨论】:

      【解决方案2】:

      如果您在保留新值之前释放了一个值,那么如果相同的值被设置两次,您可能会遇到问题。如果调用者没有保留他们自己的副本,就会发生这种情况,例如当他们从尝试设置它的同一个对象中获取值时,如下所示:

      object.value = object.value;
      

      该语句将导致对象在再次保留之前被释放,这可能导致内存被释放并导致悬空指针被保留。通过执行自动释放,它可以确保将相同的指针复制到自身上将正常工作。

      【讨论】:

        【解决方案3】:

        我通常把我的 setter 写成

        - (void)setValue:(NString *)input {
            if (value != input) {
                [value release];
                value = [input retain];
            }
        }
        

        这避免了输入和值都是同一个对象的问题。如果你不检查就释放它,那么你可能会完全释放它,下一行将尝试保留一个不再存在的对象。


        但是,最好的做法是复制字符串而不是保留它们:)

        【讨论】:

          【解决方案4】:

          (假设您在非 gc 环境中工作)

          1) 您可以创建一个临时变量并在保留/分配后释放临时变量。否则,您需要比较指针。延迟发布也可能掩盖线程错误(无论您认为是好是坏......)

          2) 从技术上讲,NSString 文字在程序的整个生命周期内都是有效的。即:while (1) [@"why won't i die?" release]; 产生一个无限循环。

          3) 对于显式保留、分配+初始化、新建和复制,您必须使用释放或自动释放来平衡保留计数。由于您没有发布 value1,因此静态分析可能(正确地)将其识别为泄漏。由于字符串常量永远不会消失,因此两者在这方面没有可比性。

          4) 这种说法没有错。问题出在程序的其他地方。要么您将其分配给 ivar 而不保留,要么稍后释放它。

          尝试经常使用静态分析,并尝试减少使用自动释放的次数(您无法完全避免)。

          这些都不是魔法,但您至少可以通过不到处使用自动释放来减少调用点(或非常接近)的许多问题的位置。尽可能使用手动保留/释放。

          最后,检查泄漏并在启用 NSZombies 的情况下运行。

          【讨论】:

            【解决方案5】:

            1) 由于以下原因,您将不得不进行自动释放: 当输入与值是相同的对象并且您将释放值时,它的保留计数将达到零并被释放,然后您才能通过输入再次保留它。 您可以使用保留来做到这一点,但您必须更改您的代码:

            -(void)setValue:(NSString*)input{
               if (value != input) {
                  [value autorelease];
                  value = [input retain];
               }
            }

            2) 我相信@"Text" 将被视为常量。当您想要一个不希望使用任何内存管理的对象时:

            NSString *value = [NSString stringWithString:@"Text"];
            

            这将返回一个自动释放的对象。

            3) 在这个例子中,它不是关于值的保留计数,而是关于引用值一的两个对象的保留计数。 如果您在离开该方法之前不释放 input1,您将遇到内存管理问题。

            4) 这个语句应该有效。没有什么可争论的。你宁愿使用 [NSString string]。

            注意: 对于内存管理:当你使用 alloc newcopy 时,你还必须使用 releaseautorelease同一范围内的同一对象。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-07-14
              • 1970-01-01
              • 1970-01-01
              • 2019-10-17
              • 2012-02-21
              • 2011-11-09
              • 2012-07-18
              • 1970-01-01
              相关资源
              最近更新 更多