2

好的,所以如果我写了很多代码而没有分配任何对象,那么内存去哪儿了?

例如,而不是拥有

UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];

我有

imageView.image = [UIImage imageNamed:@"image.png"];

在我所有的代码中。我看不到第二个示例中的内存发生了什么。我仍在学习,并在整个应用程序中使用第二个示例编写了大量代码,而从未分配任何对象。它在模拟器中总是运行良好,但实际设备无法处理内存并崩溃。所有关于内存管理的教程都在释放您创建的对象的意义上谈论它,但是由于我从未创建任何对象,所以我被卡住了。

4

3 回答 3

4
UIImage *myImage = [UIImage imageNamed:@"image.png"];
imageView.image = myImage;
[myImage release];

你做了双重释放。[UIImage imageNamed] 是自动释放的,因此您无需显式释放对象。您的应用程序可能由于双重发布而不是因为未发布的对象而崩溃。

阅读简单的经验法则,可可 for iphone 中的释放/自动释放混淆

规则很简单:如果您分配、复制或保留,则释放是您的责任。如果你没有,那就不是。但是,如果您需要依赖一个对象,您必须保留(并随后释放)。


更多示例:

imageView.image = [UIImage imageNamed:@"image.png"];

上面的代码是有效的,你不必发布它。但是,如果您对未发布的对象使用很多直接分配,例如这个:

foo.bar = [[SomeClass alloc] initWithSomething:@"Init"];

您可以通过添加 autorelease 轻松修复它们:

foo.bar = [[SomeClass alloc] initWithSomething:@"Init"] autorelease];

或者,如果您想要较长但可以说更合适的方式(因为您控制了释放对象的时间):

SomeClass *tempVar = [[SomeClass alloc] initWithSomething:@"Init"];
foo.bar = tempVar;
[tempVar release];
于 2011-07-25T03:44:54.357 回答
2
imageView.image = [UIImage imageNamed:@"image.png"];

这条线很棒而且正确。

在该imageNamed:方法的实现中,它可能会为 new 分配内存,将 newUIImage实例化UIImage到该内存中,然后autorelease在返回之前将它实例化。代码运行后,自动释放池会耗尽,如果没有保留它,则释放图像对象。

所以“记忆去哪儿了?”。它将进入自动释放池。但实际上,除非你打电话alloc或你不必关心。copy...retain

正如 Manny 所指出的,您的第一个片段确实过度发布并且不正确。

于 2011-07-25T03:50:52.600 回答
1

您将声明变量与分配内存/对象混淆了。在上述两种情况下,您的代码的重要部分实际上是:

[UIImage imageNamed:@"image.png"];

这段代码碰巧调用了 UIImage 类上的一个方法,该类方法做了很多事情。其中之一是 UIImage 对象的分配和初始化。在您的第一个示例中,您将此分配的对象存储到一个名为myImage. 然后,您将闪亮的新对象移动到另一个(类)变量“imageView.image”中。

UIImage *myImage = ...

在您给出的第二个示例中,您仍然将此分配的对象存储在变量中,除了在这种情况下您跳过中间分配并将对象直接存储到类变量imageView.image中。

imageView.image = [UIImage imageNamed:@"image.png"];

考虑变量与对象的一种方法是将它们与房屋进行比较。在这种情况下,变量是您的地址,对象是您的房子。有几个人可以知道你的地址,但无论他们有多少,当他们选择访问时,他们都会去同一所房子。因此,在您的示例中myImage,并且imageView.image是指向同一房屋或对象的地址,即 UIImage 的一个实例。在您的示例中,您实际上不需要创建中间变量,除非您将其用于其他目的。

至于崩溃,您应该阅读Apple 的内存管理指南。这可能需要一段时间,但您会习惯 Apple 在保留和释放对象方面遵循的标准。请注意,XCode 4.2 中新的自动引用计数缓解了很多这些问题,但它也有自己的学习曲线。但总而言之,您正在崩溃,因为您正在释放一个您不拥有的对象。UIImage 上的类方法imageNamed返回该类的自动释放实例。您不需要在代码中发送另一个版本,这可能是您的程序崩溃的根源。

于 2011-07-25T03:50:37.640 回答