澄清分配后何时释放指针
在我的上一个问题(此处)中,我遇到了一个问题收到 EXC_BAD_ACCESS 因为我正在释放刚刚分配的变量:
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
[s release];
应该是
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
但是,堆栈是我的类的保留属性。它是这样声明的:
@interface StateStack ()
@property (nonatomic, retain) NSMutableArray* stack;
@end
我的印象是,当您分配“保留”变量时,它会自动增加对象的保留计数。因此,您应该首先释放指针(如此处) 。
为什么这两个案例不同?谢谢!
In my last question (here), I had an issue where I was getting an EXC_BAD_ACCESS because I was releasing the variable I had just allocated:
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
[s release];
should have been
NSMutableArray* s = [[NSMutableArray alloc] init];
stack = s;
However, stack is a retained property of my class. It's declared like so:
@interface StateStack ()
@property (nonatomic, retain) NSMutableArray* stack;
@end
I was under the impression that when you assign a 'retain' variable, it automatically increments the retainCount of the object. So you are supposed to start by releasing your pointer (as here).
Why are these two cases different? Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Maurício 有正确的答案:一定要分配给该房产以获得 @property 的好处。为了澄清这一点,请尝试使用如下代码:
现在,如果您尝试:
您将收到错误,这意味着您尝试设置 ivar 而不是按预期设置属性。 ivar 名称和属性名称之间的这种不匹配违反了 Apple 的建议,但这是一个很好的方法,可以帮助您养成使用属性分配的习惯(当您打算这样做时)。
Maurício has the right answer: be sure to assign to the property to gain the benefits of @property. To clarify the point somewhat, try using code like this:
Now, if you try:
You'll get an error, which will mean you tried to set the ivar rather than the property as intended. This mismatch between ivar name and property name is against Apple's recommendations, but it's a fine way to help you develop the habit of using property assignment when you intend to do so.
因为您必须分配属性,而不是实例变量。当您分配给该属性时,它将再次保留该变量,然后您就不会遇到问题。您的代码应该是这样的:
这样您就不会分配给变量,而是使用属性(实际上,这是一个方法)。如果在这种情况下没有释放,那么代码中就会出现内存泄漏。
当您执行stack = s时,您直接分配给实例变量,并且该数组从未保留。
Because you had to assign the property, not the instance variable. When you assign to the property it's going to retain the variable again and then you're not going to have the issue. Here's how your code should have been:
This way you're not assigning to the variable, but using the property (that's, in fact, a method). If you did not release in this case then you'd have a memory leak in your code.
When you did stack = s you assigned directly to the instance variable and the array was never retained.
不存在“保留变量”这样的东西。它是一个保留属性 - 意味着属性背后的 setter 方法保留新值并释放旧值。但分配给变量只是分配。事实上,人们通常建议在
init
中直接分配给实例变量的原因是这样它就不会通过 setter,因为可以想象,setter 可能会产生您不希望出现的副作用。init
(当您的对象尚未完全构造时)。注意:我在这里讨论的是正常的内存管理规则。如果您使用 ARC,这一切都会不同。但我想如果你是的话你会提到的。
There is no such thing as a "retain variable". It's a retain property — meaning the setter method behind the property retains the new value and releases the old one. But assigning to a variable just assigns. In fact, the reason people generally recommend assigning directly to the instance variable in
init
is specifically so that it doesn't go through the setter, because the setter could conceivably have side effects you don't want ininit
(when your object isn't fully constructed yet).Note: I'm talking about normal memory-management rules here. This is all different if you're using ARC. But I assume you would have mentioned if you were.
self.stack 和 stack 是两个完全不同的东西。当您使用
stack
时,您访问的是实例变量,而不是属性。这意味着不会调用您的访问器方法,这意味着不会使用自动内存管理。这就是为什么您不应在示例中释放s
的原因。如果您使用 self.stack 来代替,那么您将使用属性。编译器会将
self.stack = value
视为与[self setStack:value]
完全相同,并将self.stack
视为与相同>[自堆栈]
。由于正在使用访问器,因此将负责内存管理以匹配您定义属性的方式,并且您应该在分配值后释放它。self.stack
andstack
are two completely different things. When you usestack
, you are accessing an instance variable, not a property. This means that your accessor methods aren't called, which means automatic memory management isn't used. This is why you shouldn't releases
in your example.If you used
self.stack
instead, then you would be using a property. The compiler will treatself.stack = value
exactly the same as[self setStack:value]
, andself.stack
the same as[self stack]
. Since accessors are being used, memory management will be taken care of to match the way you defined your property, and you should release a value after assigning it.