Objective-C初始化和自动释放池怪癖

问题描述 投票:0回答:2

在类接口中,我定义了一些属性

@property (strong,nonatomic) id < Protocol > initEst;   // Initial estimate

然后再在类消息中输入我的意思

...
@autoreleasepool
{
    something = ...;            // alloc'd and init'd here ...
    self.initEst = something;   // retain as class variable for later
}
...

[我认为ARC可以正常工作,以后需要时self.initEst将可用。

但不是。它不是nil,但是调试器显示它是指向[0]的有效指针?我怀疑自动释放池会以某种方式释放它,因此我尝试保留它,但没有任何乐趣。另外,当我以任何方式向它发送消息时,我会得到关于CFString的非常奇怪的错误,我没有在附近使用它。

发生了什么事?

[另外,有人可以确认在autoreleasepool内进行某些工作,然后将结果保留在类变量中以供以后在autoreleasepool之外使用时没有错吗?与上面的操作几乎相同,但名称不同。

objective-c automatic-ref-counting initializer autorelease
2个回答
0
投票

全部有关ARC自动内存管理的规则。初始化程序对如何处理返回的值有特殊的规则:它将保留并返回。参见https://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-init

一般而言,Objective-C,尤其是ARC,对于方法名称的含义有一些非常严格的规则。 initXXX的意思是“这是一个初始化程序”。如果这不是初始化程序,请不要使用init前缀。

您可以完全关闭ARC并自行管理内存,但是遵守约定会更容易,并且在与其他语言(例如Swift)进行交互的情况下更适合。


-1
投票

我已经对此进行了更多测试,并且似乎有[[3个条件可以使这个特殊问题出现。

在我的特殊情况下,ivar的Protocol也与包含类的相同。这似乎是此问题浮出水面的一项附加要求(此处指的是我之前未提及此问题的答案)。

因此,请详细说明我先前的答案。如果

    initXXX是一个ivar
  1. id类型的
  2. 实现一个Protocol,它与包含的类的
  3. same
相同然后,Objective-C + ARC编译器将愉快地编译代码,但无法执行它。

这里是我用来测试的代码示例

@interface Dog : NSObject < Animal > @property (nonatomic,strong) id < Animal > initState; @end

类似这样的东西会引起问题,只是因为名称以

init

开头。更改名称,所有问题都会消失。作为参考,此生成的运行时错误为

已取消分配时已释放的狗对象

此代码段非常抽象,但是这可能会在您需要指定一些初始条件以及很自然地将一些ivar initXxx命名的地方咬住您,但是请注意,如果您使用Objective-C,您将没有那么奢侈或编译器会警告您这是错误的。

原始错误似乎与内存分配有关,并且使我怀疑我使用

autoreleasepool

的方式,但是现在我相当确信这与问题无关。
© www.soinside.com 2019 - 2024. All rights reserved.