【问题标题】:iOS objective-c object: When to use release and when to not use itiOS Objective-C 对象:何时使用 release 何时不使用
【发布时间】:2018-09-13 13:01:39
【问题描述】:

我在 iOS 下,我正在使用 delphi Tokyo 进行开发,这是我的代码:

      aUIImage := TUIImage.Wrap(TUIImage.alloc.initWithCGImage(aCGImageRef));
      try

        aData := TNSData.Wrap(UIImageJPEGRepresentation((aUIImage as ILocalObject).GetObjectID, cWin_DefaultJPGCompressionRate / 100));
        try
          aWorkPicStream.WriteBuffer(aData.bytes^, aData.length);
        finally
          aData.release; // << this make my code will crash (later not now)
        end;

      finally
        aUIImage.release;
      end;

在执行之前的代码之后我在执行的稍晚时出现了这个错误:

myproj  [E][W][I][D][V] Error => Access violation at address 0000000184D4891C, accessing address 0000000107FD286C
At address: $0000000184D4891C (objc_msgSend + 28)

Call stack:
myproj                    $0000000103E00548 Grijjy.Errorreporting.TgoExceptionReporter.GlobalGetExceptionStackInfo(TExceptionRecord*) + 196
myproj                    $00000001030DF0EC Sysutils.Exception.RaisingException(TExceptionRecord*) + 88
myproj                    $0000000103116164 Sysutils.RaiseExceptObject(TExceptionRecord*) + 84
myproj                    $00000001030BB498 _RaiseAtExcept(TObject*, Pointer) + 128
myproj                    $00000001030DD900 Internal.Excutils.SignalConverter(NativeUInt, NativeUInt, NativeUInt) + 68
libobjc.A.dylib           $0000000184D5213C <redacted> + 844
CoreFoundation            $0000000185A40AAC _CFAutoreleasePoolPop + 28
Foundation                $00000001864FB960 <redacted> + 148
myproj                    $00000001031B426C Classes.ThreadProc(Classes.TThread*) + 948
myproj                    $00000

如果我评论 aData.release; 行,那么我不会遇到任何错误。

为什么?如何知道什么时候必须调用 release 什么时候不能调用 release ?

【问题讨论】:

  • @RudyVelthuis 好的,但是这样为什么 aUIImage.release;不要引发任何错误?
  • @RudyVelthuis :不幸的是,原始文档什么也没说:(

标签: ios delphi firemonkey


【解决方案1】:

iOS 的 ARC 规则相当简单,如 Apple's Basic Memory Management Rules 中所述。

名称以allocnewcopymutableCopy 开头的方法不需要调用retain。相反,如果你调用它,你会造成内存泄漏,因为retain 太多了。但他们确实需要releaseautorelease。这些对象实例是你创建的,在 Objective-C 下,它们在构造时会自动保留。

aUIImage 是使用alloc 构建的,您拥有它并负责使用release 发布它。另一方面,您不拥有aData,它将由系统处理。

要记住的另一件事是,对于您不拥有的对象,您可能需要同时调用 retainrelease 以保持对象实例在您使用时保持活动状态。由于接收到的对象通常保证在接收到的方法中保持有效,因此您不必在代码中对 aData 调用 retainrelease


retainCount 方法返回 Objective-C 对象实例的当前引用计数。这个数字纯粹是信息性的,在 iOS 或 macOS 下没有调试价值,但它足以显示 Objective-C 和 Delphi 内存管理之间的交互,并且有时会有所帮助。

来自苹果关于retainCount的文档:

retainCount - 不要使用这种方法

此方法在调试内存管理问题时没有任何价值。 因为任意数量的框架对象都可能在 为了保持对它的引用,同时自动释放 池可以在一个对象上持有任意数量的延迟释放,它 您不太可能从这种方法中获得有用的信息。

【讨论】:

    【解决方案2】:

    除了上述规则之外,对于一般调试,您可以对目标运行静态分析 - “Cmnd+Shift+B(Build)”。这将为可能的内存泄漏提供一些见解。 (注意:在某些情况下,它可能表示对象可能存在内存泄漏,但该对象可能会在代码中的其他位置释放。这取决于您的实现)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-22
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多