Objective-C指针/内存pipe理问题
我正在testing下面的代码。 在接口文件中声明ffv。
ffv = [[FullFunctionView alloc] initWithFrame:self.view.bounds]; NSLog(@"%i", [ffv retainCount]); // prints 1 [self.view insertSubview:ffv belowSubview:switchViewsBtn]; NSLog(@"%i", [ffv retainCount]); // prints 2 [ffv release]; // you can release it now since the view has ownership of ffv NSLog(@"%i", [ffv retainCount]); // prints 1 if (ffv == nil) NSLog(@"ffv is nil"); // "ffv is nil" is not printed [ffv testMethod]; // "test method called" is printed
这是我的[ffv testMethod]实现
- (void)testMethod { NSLog(@"test method called"); }
在这种情况下我推论的是,即使你释放一个保留数为2的对象,你也会失去那个对象的所有权,但是引用仍然保留。
现在,我的问题是:
- 我的演绎是否正确?
- 还有什么重要的,可以从这个推论?
- 仍然保持(使用)ffv和从ffv调用方法引起的并发症是什么? (我的观点是,这是好的,因为视图将永远拥有ffv,并且不会释放它,直到有人调用viewDidUnload。只要我不传递ffv的引用其他对象。
1)我的演绎是否正确?
你的推论是正确的。 “ 内存pipe理编程指南”解释了每个对象都有一个或多个所有者。 您拥有使用任何以alloc
, new
, copy
或mutableCopy
开头的方法创build的任何对象。 您也可以使用retain来获取对象的所有权。 当你完成一个对象,你必须放弃所有权使用release
或autorelease
。
释放对象不会改变任何引用该对象的variables的值。 您的variables包含对象的内存地址,直到您重新分配为止,而不pipe该对象具有多less保留计数。 即使对象的保留计数变为零,导致对象被释放,variables仍将指向同一地址。 如果尝试在释放对象后访问对象,则应用程序通常会与EXC_BAD_ACCESS一起崩溃。 这是一个常见的内存pipe理错误。
2)还有什么重要的可以从这个推论?
没有任何想法。
3)由ffv保持(使用)ffv和调用方法引起的并发症是什么? (我的观点是,这是好的,因为视图将永远拥有ffv,并且不会释放它,直到有人调用viewDidUnload。只要我不传递ffv的引用其他对象。
当你调用release
,你告诉Objective C运行时你不再需要访问这个对象。 虽然可能有很多像这样的情况下,你知道对象将仍然存在的情况下,实际上,你真的不应该在调用release
后访问对象。 你只是在诱惑自己的命运,并设置自己的未来错误。
我个人不喜欢用release
声明来encryption我的代码,因为我不相信自己在100%的时间记住它们。 相反,我喜欢自动释放我的variables,只要我像这样分配它们:
ffv = [[[FullFunctionView alloc] initWithFrame:self.view.bounds] autorelease];
这保证了ffv至less会存在直到方法结束。 它将在此后不久发布,通常在运行循环的下一次迭代之前。 (理论上,如果你在一个紧密的循环中分配大量的临时对象,这可能消耗过多的内存,但实际上我从来没有遇到过这种情况,如果我这样做的话,将会很容易优化。
在你释放它之后使用ffv
有几个问题,它只被视图控制器的视图所保留。
1)它引入了未来错误的可能性,因为后来你可能不会记得ffv
是不被保留的。 当你释放视图(例如用另一个视图replace视图)时,你有一个悬挂的指针,你仍然有一个引用。
2)在UIViewController
的特殊情况下,视图可以在任何时候被释放(你通常不会自己调用viewDidUnload
)。 UIViewController
的默认行为在接收到内存警告并且视图当前不可见的情况下是释放视图,所以除非在viewDidUnload
中将引用设置为nil,否则即使您从未显式释放查看你自己。
直到保留计数变为0,对象才会被释放 。只要不释放,就可以继续使用它。 通过保留它,确保它不会在你的脚下被释放。 然而,如果您保留另一个您知道保留第一个对象的对象,则可以使用这种“间接保留”的forms。 不要抱怨,当你以后移动的东西,事情开始打破,虽然。
if (ffv == nil) NSLog(@"ffv is nil"); // "ffv is nil" is not printed
这是正确的, 即使在那个时候 ,释放对象也不 会将指针设置为零。 好的做法是在释放指针后始终将指针设置为零。 你说的是对的,你说的是对的,因为这个观点还是有的。 但是这不是你应该考虑的问题。 如果你想使用这个对象,并且希望它是活着的,就保留它。 无所谓保留它。 你的对象与其他对象无关。 你想要它,保留它。 你完成了,释放它, 并设置你的指针为零 。 如果你不把它设置为零,其他人也将它释放,那么你将有一个悬挂指针指向一个被交易的对象,这会导致你崩溃和不满。
所以这:
[ffv release]; // you can release it now since the view has ownership of ffv ffv = nil; // you released it, so that means you don't want it anymore, so set the pointer to nil
如果你仍然想使用它,不要释放它,直到你完成它。
那么,我不确定'失去'的所有权是正确的。 在Objective-C中,你必须仔细编组你的对象的所有权。 如果你创build或保留一个对象,你有责任释放它(直接或通过autorelease池)。 但是,当你调用release的时候,你不会失去对这个对象的引用,如果其他东西保留了,它仍然会在内存中,你的指针仍然可能指向它。
你有一个指针ffv,它只是一个指向某个内存的指针,并且你在ffv指向的第一行创build了这个对象。
通过调用release
,你声明你不再需要指向一个有效的对象, 在这种情况下,你会很乐意让对象被释放。 指针仍指向该位的内存,它仍然存在,因为它的保留计数增加了分配给视图。
[ffv testMethod]
有可能不起作用,因为它跟在release
[ffv testMethod]
,可能不会指向有效的对象。 它只能起作用,因为别的东西在活着。 ffv仍然具有与第一次分配时相同的地址值。
所以为了:
- 你的推论是正确的。
- 不是真的。
-
release
呼叫后,您不应使用ffv。 你不能保证对象会在你身边。
这些是我们在这里使用的指针,而不是像在Java或C#中find的引用。 你必须编组你的对象的所有权,你创build它,有一些指针,并通过谨慎的pipe理保留和释放调用,只要你需要它保存在内存中。