Objective c 释放、解除锁定和自引用

Objective c 释放、解除锁定和自引用,objective-c,memory-management,null,Objective C,Memory Management,Null,所以我想我已经解决了所有这些问题。然后突然间我发现了一个错误(崩溃),我想不出来。然后在做了补救事故的研究之后,我注意到我认为我所知道的关于这些关键领域的一切都有些错误 下面是8个问题,我只是希望有人能回答——这些问题的答案将极大地帮助我的理解回到正轨。提前谢谢 Q1)如果一个对象的引用为零,调用Release可以吗?这应该是无害的,对吧 Q2)如果某个对象的引用已被释放,并且引用计数为0,则可以对该对象调用Release吗 问题3)发布后是否需要将引用设置为nil?如果不将其设置为零会发生什么

所以我想我已经解决了所有这些问题。然后突然间我发现了一个错误(崩溃),我想不出来。然后在做了补救事故的研究之后,我注意到我认为我所知道的关于这些关键领域的一切都有些错误

下面是8个问题,我只是希望有人能回答——这些问题的答案将极大地帮助我的理解回到正轨。提前谢谢

Q1)如果一个对象的引用为零,调用Release可以吗?这应该是无害的,对吧

Q2)如果某个对象的引用已被释放,并且引用计数为0,则可以对该对象调用Release吗

问题3)发布后是否需要将引用设置为nil?如果不将其设置为零会发生什么

问题4)nil和NULL之间真的有区别吗?或者仅仅通过浏览对象类型就可以帮助读者/开发人员了解对象类型,这只是一种语义上的东西吗

Q5)使用属性需要使用“Self”指针吗

Q6)使用实例变量要求不使用“Self”指针

Q7)我什么时候会想使用实例变量而不是它的属性?我认为值类型的数据成员是可以接受的,因为它们不涉及释放和保留

Q8)是否需要从dealloc函数中调用对象的dealloc?
在许多例子中,我看到发布被调用,但不是Dealloc-这样的教程不正确吗?

您可能应该将这个问题分成多个不同的问题,但我要咬一口

  • 是的,任何发送到nil的消息都是不可操作的
  • 否。引用计数为0的对象已被销毁或即将被销毁,发送给该对象的任何消息都将导致崩溃,或者最多导致异常
  • 这要视情况而定。如果您在
    -dealoc
    中发布内容,那么可能不会。如果对象的作用域是特定的方法,那么可能不是。如果它是一个可重复使用的ivar,我会说是的。在前两种情况下,如果不将指针设置为nil,将不会发生任何事情,因为您通常无法再访问这些指针。但在最后一种情况下,您仍然可以访问指针,它指向解除分配的内存。如果您向其发送消息或尝试取消引用,您的应用程序将崩溃
  • 它们都等于0。按照惯例,
    nil
    用于对象指针,而
    NULL
    用于任何其他指针,但混合使用它们不会导致任何问题
  • 如果要调用属性getter/setter,则选择yes。如果您想访问它直接封装的ivar(不常见),则不需要
  • 不,您可以使用语法
    self->ivar
    访问实例变量。事实上,当您只键入
    ivar
    时,编译器会隐式地添加
    自->
    解引用
  • 不知道你在这里是什么意思
  • 您唯一应该调用
    -dealloc
    的时间是调用
    [super dealloc]时在您自己的
    -dealloc
    方法中。对于任何其他对象,您应该始终只调用
    -release
  • A1)
    [nil release]
    可以(不会做任何事情)

    A2)不可以。解除分配后不要触摸物体。释放后应将其设置为零

    A3)没有必要将已释放的指针设置为nil,但会得到悬空指针(即,无法判断对象是否有效)。将属性设置为nil通常用于释放底层ivar,因此如果不这样做,可能会导致内存泄漏

    A4)nil和NULL均为零,因此在技术上是相同的

    A5)是的,您必须使用
    self.someProperty
    作为属性,就像使用
    [self-someProperty]
    作为方法一样

    A6)self本质上是一个结构,因此可以像这样访问ivar:
    self->someIvar
    。不过,没有必要这样做

    A7)无论出于何种原因,您都不想运行setter/getter方法。当setter不允许nil值时,我会使用它,我需要释放变量


    A8)当调用释放的次数正确时,将自动调用dealloc。你不应该直接打电话给dealloc(超级dealloc除外)

    其他人已经回答了1-6个问题

    (7) Apple建议您在init和dealloc中直接使用实例变量。这主要是因为对象(特别是如果它是子类的)仅在这两种方法中进行了部分设置,因此调用setter/getter可能会导致不正确的行为(如果它们有非平凡的操作)。通常,您可以直接(而不是通过getter)安全地访问对象中的ivar,这样做会稍微有效一些(仅在iPhone上相关)。通常,您应该在所有情况下使用setter,尤其是当您的对象可能是子类的或者其他人可能正在观察该属性时


    (8) 您永远不会调用dealloc(dealloc方法中的[super dealloc]除外)。如果您拥有另一个对象的所有权,那么您应该放弃该所有权(通过调用release或autorelease)。如果合适,系统将调用对象上的dealloc。但你自己从来不打电话给Dealoc。阅读(只有9段,理解起来很重要)。

    好的。我已经证实,没有将B设为零就成功了。 所以,现在,在创建B控制器时(当我想导航到它时),我不检查nil

    相反,我释放B,然后创建控制器并将其分配给B。 然后,在A的viewDidAppear方法中,我释放了B

    我相信这条线现在已经结束了。谢谢

    它们的类型不同。它们都是零,但是NULL是一个void*,nil是一个id,nil是一个类指针。

    At(2)应该提到NSZombieEnabled。它使调试alloc问题变得容易