代码示例:为什么我释放这个 NSString 对象后仍然可以访问它?

发布于 2024-08-06 16:49:29 字数 811 浏览 10 评论 0原文

我只是编写了一些探索性代码来巩固我对 Objective-C 的理解,但我遇到了这个我不太明白的例子。我定义此方法并运行代码:

- (NSString *)stringMethod
{
    NSString *stringPointer = [[NSString alloc] initWithFormat:@"string inside stringPointer"];
    [stringPointer release];
    [stringPointer release];
    NSLog(@"retain count of stringPointer is %i", [stringPointer retainCount]);
    return stringPointer;
}

运行代码并调用此方法后,我注意到一些事情:

  1. 通常,如果我尝试访问在达到零保留计数后应该释放的内容,我会收到 EXC_BAD_ACCESS 错误。在这里,我收到了 malloc“双重释放”错误。为什么会这样?

  2. 无论我向代码中添加多少行“[stringPointer release]”,NSLog 都会报告保留计数为 1。当我添加更多版本时,我只会收到更多“双重释放”错误。为什么发布语句没有按预期工作?

  3. 虽然我已经过度释放了 stringPointer 并且收到了一堆“双重释放”错误,但返回值仍然像什么都没发生一样工作(我在主代码中有另一个 NSLog 报告返回值)。程序继续正常运行。再次,有人可以解释为什么会发生这种情况吗?

这些例子相当琐碎,但我试图完全掌握正在发生的事情。谢谢!

I was just writing some exploratory code to solidify my understanding of Objective-C and I came across this example that I don't quite get. I define this method and run the code:

- (NSString *)stringMethod
{
    NSString *stringPointer = [[NSString alloc] initWithFormat:@"string inside stringPointer"];
    [stringPointer release];
    [stringPointer release];
    NSLog(@"retain count of stringPointer is %i", [stringPointer retainCount]);
    return stringPointer;
}

After running the code and calling this method, I notice a few things:

  1. Normally, if I try to access something that's supposedly dealloced after hitting zero retain count, I get a EXC_BAD_ACCESS error. Here, I get a malloc "double free" error instead. Why is that?

  2. No matter how many lines of "[stringPointer release]" I add to the code, NSLog reports a retain count of 1. When I add more releases I just get more "double free" errors. Why aren't the release statements working as expected?

  3. Although I've over-released stringPointer and I've received a bunch of "double free" errors, the return value still works as if nothing happened (I have another NSLog in the main code that reports the return value). The program continues to run normally. Again, can someone explain why this happens?

These examples are fairly trivial, but I'm trying to get a full grasp of what's going on. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(3

在梵高的星空下 2024-08-13 16:49:29

您收到了双重释放错误,因为您释放了两次并导致了两条释放消息。 =P

请记住,释放并不意味着其内存地址处的数据会立即被销毁。它只是被标记为未使用,这样内核就知道,在将来的某个时刻,它可以自由地用于另一条数据。在那之前(这在您的应用程序空间中完全是不确定的),数据将保留在那里。

再说一遍:释放(和解除分配)并不需要立即销毁字节级别的数据。它只是内核的一个标记。

You're getting a double free error because you are releasing twice and causing two dealloc messages. =P

Keep in mind that just because you release doesn't doesn't mean the data at its memory address is immediately destroyed. It's just being marked as unused so the kernel knows that, at some point in the future, it is free to be used for another piece of data. Until that point (which is totally nondeterministic in your app space), the data will remain there.

So again: releasing (and dealloc'ing) doesn't necessitate immediate data destruction on the byte level. It's just a marker for the kernel.

韵柒 2024-08-13 16:49:29

这里发生了一些事情。首先,释放对象并不一定会清除该对象以前占用的任何内存。它只是将其标记为免费。除非您执行其他操作导致内存被重新使用,否则旧数据将一直存在。

在 NSString 的特定情况下,它是一个类簇,这意味着您从 alloc/init 返回的实际类是 NSString 的某个具体子类,而不是 NSString 实例。对于“常量”字符串,这是一个极其轻量级的结构,仅维护一个指向 C 字符串常量的指针。无论您复制该字符串多少次,或者释放它多少次,都不会影响指向常量 C 字符串的指针的有效性。

在这种情况下,以及在可变字符串或实际使用格式字符和参数的格式化字符串的情况下,尝试检查 [stringPointer 类]。也许这三个人都会有不同的班级。

There are a couple of things going on here. First, deallocing an object doesn't necessarily clear any of the memory the object formerly occupied. It just marks it as free. Unless you do something else that causes that memory to be re-used, the old data will just hang around.

In the specific case of NSString, it's a class cluster, which means that the actual class you get back from alloc/init is some concrete subclass of NSString, not an NSString instance. For "constant" strings, this is an extremely light-weight structure that just maintains a pointer to the C-string constant. No matter how many copies of that striing you make, or how many times you release it, you won't affect the validity of the pointer to the constant C string.

Try examining [stringPointer class] in this case, as well as in the case of a mutable string, or a formatted string that actually uses a format character and arguments. Probably all three will turn out to have different classes.

黒涩兲箜 2024-08-13 16:49:29

keepCount 总是打印 1 可能是由优化引起的 - 当release注意到它将被释放时,没有理由将retainCount更新为零(因为此时没有人应该拥有对该对象的引用)而不是更新retainCount只是解除分配它。

The retainCount always printing one is probably caused by optimization - when release notices that its going to be deallocated, there's no reason to update the retainCount to zero (as at this point nobody should have a reference to the object) and instead of updating the retainCount just deallocates it.

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