泄漏或崩溃 - 自动释放和释放之间的区别
我有一个理解问题。给出了此方法:
- (NSArray*)test {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
NSString *result = [[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSMacOSRomanStringEncoding];
result = [result stringByAppendingString:@"something"];
NSArray *arr = [NSArray arrayWithObject:result];
//[result release];
return arr;
}
如果我取消注释 release
,应用程序将崩溃并表示无法访问已发布的对象。
如果不释放
结果
字符串,Instruments 将报告泄漏 (NSPlaceholderString)。
我可以在分配它的同一行上自动释放它,这将解决问题(我目前正在我的应用程序中执行此操作)。
如果我理解正确的话 stringByAppendingString:
应该创建一个自动释放的对象,以便可以释放“旧”结果。然后方法arrayWithObject:
应该将对象复制
到数组中。所以我的想法是在将字符串复制到数组后释放它。
我的知识是否遗漏或有问题?
I have a comprehension question. This method is given:
- (NSArray*)test {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];
NSString *result = [[NSString alloc] initWithBytes:[data bytes]
length:[data length]
encoding:NSMacOSRomanStringEncoding];
result = [result stringByAppendingString:@"something"];
NSArray *arr = [NSArray arrayWithObject:result];
//[result release];
return arr;
}
If I uncomment the release
the App would crash and say it cannot access a released object.
By not release
ing the result
string Instruments would report a leak (NSPlaceholderString).
I can autorelease
it on the same line I alloc
it, that would solve the problem (which I'm currently doing in my App).
If I understand it correctly stringByAppendingString:
should create an autoreleased object so the 'old' result could be deallocated. Then the method arrayWithObject:
should copy
the object into an array. So my thought was to release the string after it was copied to the array.
Am I missing something or something wrong with my knowledge?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
让我们逐行查看您的代码。
这将创建一个数据对象。您并不拥有它,但它会在该方法的剩余时间内保留下来。到目前为止,一切都很好。
这将创建一个您拥有的字符串对象。再说一次,这里没问题——我们只需要稍后发布它。
您丢弃对
result
中的字符串对象的引用,并存储一个不属于您的新字符串对象。这是泄漏,因为您无法再释放原始字符串。另外,您正确地注意到新字符串可以被视为自动释放的对象 - 这意味着您不应该释放它。与您的看法相反,这并没有复制任何内容。它只是保留对新字符串的引用并保留它。
此时您不应该释放
result
,因为它包含的对象不是您所拥有的 — 您是从stringByAppendingString:
获取的,而不是从带有new 的方法获取的其名称中包含
、alloc
、retain
或copy
。释放这个不属于您的对象几乎肯定会在某个时刻导致崩溃。您拥有且应该释放的旧对象在两行之前就丢失了,并且释放其他对象来代替它也无济于事。Let's go through your code line by line.
This creates a data object. You don't own it, but it will stick around for the rest of the method's time. So far, so good.
This creates a string object that you own. Again, no problem here — we just need to release it later.
You throw away your reference to the string object that was in
result
and store a new string object that you do not own. This is a leak because you can no longer release the original string. Also, you're correct in noting that the new string can be treated as an autoreleased object — which means you should not release it.Contrary to your belief, this does not copy anything. It merely keeps a reference to the new string and retains it.
You should not release
result
at this point, because the object it contains is not one you own — you got it fromstringByAppendingString:
, not from a method withnew
,alloc
,retain
orcopy
in its name. Releasing this object that you do not own will almost certainly result in a crash at some point. The old object that you own and should release was lost two lines earlier, and releasing something else in its place won't help.此行用新的自动释放字符串替换第一个分配的字符串。
所以第一个字符串被泄漏,第二个字符串不应该被释放。这解释了为什么取消注释发布行会崩溃。
This line replaces the first allocated string by a new autoreleased string.
So the first string is leaked and the second one should not be released. This explains why uncommenting the release line crashes.