Objective-C中的内存管理,将一个新数组从另一个函数初始化为自动释放的数组

时间:2022-09-25 08:40:36

I'm trying to understand memory management better. If I have a function that returns an autorelease NSArray like this

我想更好地理解内存管理。如果我有一个返回像这样的自动释放NSArray的函数

// DataClass
    - (NSArray *)getData {
       NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
       // do some stuff to get data from sqlite
       return array;
    }

then in another class file, I want to use this getData. I have a property

然后在另一个类文件中,我想使用这个getData。我有一个房产

@property (nonatomic, retain) NSArray *myData;

- viewDidLoad {
    NSMutableArray *data = [[NSMutableArray alloc] init];
    data = [DataClass getData];
    self.myData = data;
    [data release];
}

Why do I get a bad access error in this case? I know it's because of [data release], but I thought that since the getData method returns an autorelease NSArray, and because I initialize a new NSMutableArray with alloc/init, then I'd need to release it? Or is what happening is even though I initialize data with alloc/init, I then am not even using it because with the data=[DataClass getData] statement, I point to a different NSArray, and then try to release that already autoreleased NSArray from getData, and then the NSMutableArray data is still floating around in memory somewhere? Thanks in advance.

在这种情况下,为什么会出现错误的访问错误?我知道这是因为[数据发布],但我认为因为getData方法返回一个自动释放NSArray,并且因为我使用alloc / init初始化一个新的NSMutableArray,那么我需要释放它吗?或者正在发生的事情即使我用alloc / init初始化数据,我甚至不使用它,因为使用data = [DataClass getData]语句,我指向一个不同的NSArray,然后尝试释放已经自动释放的NSArray getData,然后NSMutableArray数据仍在内存中漂浮?提前致谢。

2 个解决方案

#1


1  

Your guess is correct. :-)

你的猜测是正确的。 :-)

First of all, as written, in viewDidLoad you leak the data you alloc/init on line 1 when you assign data the result of calling getData on line 2.

首先,正如所写,在viewDidLoad中,当你为数据分配第2行调用getData的结果时,你会泄漏第1行的alloc / init数据。

And then, you are correct, that data at this point is pointing at an autoreleased object. So calling release on it is a bad thing.

然后,你是对的,此时的数据指向一个自动释放的对象。因此,调用它是一件坏事。

Frankly, in your viewDidLoad method, you really don't need the call to getData at all. The complete and appropriate sequence for this kind of operation is:

坦率地说,在你的viewDidLoad方法中,你根本不需要调用getData。这种操作的完整和适当的顺序是:

NSMutableArray *array = [[NSMutableArray alloc] init];
// here is where you could fill array with your data, or call a method to 
// which you pass array to be filled.
self.data = array;
[array release];

assuming that the data property is defined with retain. By using the self. prefix, you get a retain done for you.

假设data属性是使用retain定义的。通过使用自我。前缀,你得到一个保留。

Does this help?

这有帮助吗?

#2


0  

There are two possible problems with your code. The first is certain:

您的代码有两个可能的问题。首先是肯定的:

 NSMutableArray *data = [[NSMutableArray alloc] init];
 data = [DataClass getData];

This is not the correct pattern for initializing objects. Let's assume a class method called getData exists, and does what you want (which may not be the case, more on that later). The first line would allocate memory for a new array, and return a pointer to it. The second line would then immediately reassign that pointer to point to a different (autoreleased) array, leaking the first array in the process.

这不是初始化对象的正确模式。让我们假设一个名为getData的类方法存在,并做你想要的(可能不是这种情况,稍后会更多)。第一行将为新数组分配内存,并返回指向它的指针。然后第二行将立即重新指定该指针指向一个不同的(自动释放的)数组,从而泄漏进程中的第一个数组。

Secondly, your getData method has the following signature:

其次,您的getData方法具有以下签名:

- (NSArray *)getData;

Implying that it is an instance method, meaning you send it to an instance of the DataClass. However, your code that calls the method does so by sending the message to the class itself, not an instance of it. This may just be a typo in your posting, but better safe than sorry.

暗示它是一个实例方法,意味着您将其发送到DataClass的实例。但是,调用该方法的代码通过将消息发送给类本身而不是它的实例来实现。这可能只是您帖子中的拼写错误,但比抱歉更安全。

#1


1  

Your guess is correct. :-)

你的猜测是正确的。 :-)

First of all, as written, in viewDidLoad you leak the data you alloc/init on line 1 when you assign data the result of calling getData on line 2.

首先,正如所写,在viewDidLoad中,当你为数据分配第2行调用getData的结果时,你会泄漏第1行的alloc / init数据。

And then, you are correct, that data at this point is pointing at an autoreleased object. So calling release on it is a bad thing.

然后,你是对的,此时的数据指向一个自动释放的对象。因此,调用它是一件坏事。

Frankly, in your viewDidLoad method, you really don't need the call to getData at all. The complete and appropriate sequence for this kind of operation is:

坦率地说,在你的viewDidLoad方法中,你根本不需要调用getData。这种操作的完整和适当的顺序是:

NSMutableArray *array = [[NSMutableArray alloc] init];
// here is where you could fill array with your data, or call a method to 
// which you pass array to be filled.
self.data = array;
[array release];

assuming that the data property is defined with retain. By using the self. prefix, you get a retain done for you.

假设data属性是使用retain定义的。通过使用自我。前缀,你得到一个保留。

Does this help?

这有帮助吗?

#2


0  

There are two possible problems with your code. The first is certain:

您的代码有两个可能的问题。首先是肯定的:

 NSMutableArray *data = [[NSMutableArray alloc] init];
 data = [DataClass getData];

This is not the correct pattern for initializing objects. Let's assume a class method called getData exists, and does what you want (which may not be the case, more on that later). The first line would allocate memory for a new array, and return a pointer to it. The second line would then immediately reassign that pointer to point to a different (autoreleased) array, leaking the first array in the process.

这不是初始化对象的正确模式。让我们假设一个名为getData的类方法存在,并做你想要的(可能不是这种情况,稍后会更多)。第一行将为新数组分配内存,并返回指向它的指针。然后第二行将立即重新指定该指针指向一个不同的(自动释放的)数组,从而泄漏进程中的第一个数组。

Secondly, your getData method has the following signature:

其次,您的getData方法具有以下签名:

- (NSArray *)getData;

Implying that it is an instance method, meaning you send it to an instance of the DataClass. However, your code that calls the method does so by sending the message to the class itself, not an instance of it. This may just be a typo in your posting, but better safe than sorry.

暗示它是一个实例方法,意味着您将其发送到DataClass的实例。但是,调用该方法的代码通过将消息发送给类本身而不是它的实例来实现。这可能只是您帖子中的拼写错误,但比抱歉更安全。