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的实例。但是,调用该方法的代码通过将消息发送给类本身而不是它的实例来实现。这可能只是您帖子中的拼写错误,但比抱歉更安全。