泄漏或崩溃 - 自动释放和释放之间的区别

发布于 2024-10-09 08:25:07 字数 840 浏览 10 评论 0原文

我有一个理解问题。给出了此方法:

- (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 releaseing 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

远山浅 2024-10-16 08:25:07

让我们逐行查看您的代码。

- (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"];

您丢弃对 result 中的字符串对象的引用,并存储一个不属于您的新字符串对象。这是泄漏,因为您无法再释放原始字符串。另外,您正确地注意到新字符串可以被视为自动释放的对象 - 这意味着您不应该释放它。

NSArray *arr = [NSArray arrayWithObject:result];

与您的看法相反,这并没有复制任何内容。它只是保留对新字符串的引用并保留它。

//[result release];

此时您不应该释放 result,因为它包含的对象不是您所拥有的 — 您是从 stringByAppendingString: 获取的,而不是从带有 new 的方法获取的其名称中包含allocretaincopy。释放这个不属于您的对象几乎肯定会在某个时刻导致崩溃。您拥有且应该释放的旧对象在两行之前就丢失了,并且释放其他对象来代替它也无济于事。

Let's go through your code line by line.

- (NSArray*)test {
 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://stackoverflow.com/"]];

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.

 NSString *result = [[NSString alloc] initWithBytes:[data bytes] 
                                             length:[data length] 
                                           encoding:NSMacOSRomanStringEncoding];

This creates a string object that you own. Again, no problem here — we just need to release it later.

result = [result stringByAppendingString:@"something"];

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.

NSArray *arr = [NSArray arrayWithObject:result];

Contrary to your belief, this does not copy anything. It merely keeps a reference to the new string and retains it.

//[result release];

You should not release result at this point, because the object it contains is not one you own — you got it from stringByAppendingString:, not from a method with new, alloc, retain or copy 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.

朮生 2024-10-16 08:25:07
result = [result stringByAppendingString:@"something"];

此行用新的自动释放字符串替换第一个分配的字符串。

所以第一个字符串被泄漏,第二个字符串不应该被释放。这解释了为什么取消注释发布行会崩溃。

result = [result stringByAppendingString:@"something"];

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文