为什么仪器不会“泄漏”?模板能捕获我的 iOS 应用程序上的内存泄漏吗?

发布于 2024-09-11 15:32:47 字数 538 浏览 5 评论 0原文

我正在深入研究 iOS 开发并熟悉这些工具。每天结束时,我都会在应用程序上执行“使用仪器工具运行 -> 泄漏”,以检查当天可能实施的任何内存泄漏。它似乎很少检测到任何泄漏,虽然我想认为我只是一个天生的 iOS 程序员,但我拒绝相信这一点;)

无论如何,我刚刚在我的代码中发现了我认为的内存泄漏,但它并没有不要被 Instruments 抓住。我有这行代码...

gkSession = [[GKSession alloc] initWithSessionID:@"testID" displayName:@"Temp Display Name" sessionMode:GKSessionModeClient];

我发现我没有在代码中的任何地方调用 release 。我的问题是...

  1. 这是内存泄漏吗?
  2. 如果是这样,仪器可能无法捕获它的原因是什么?

我明显担心的是我的代码中存在内存泄漏,而 Instruments 没有捕获它们。

预先非常感谢您的帮助!

I'm diving into iOS development and am getting familiar with the tools. At the end of every day, I perform a "Run with instruments tool -> Leaks" on my app to check for any memory leaks I may have implemented that day. It rarely seems to detect any leaks and, while I'd like to think I'm just a natural iOS programmer, I refuse to believe that ;)

Anyhow, I just found what I think is a memory leak in my code and it doesn't get caught by Instruments. I have this line of code...

gkSession = [[GKSession alloc] initWithSessionID:@"testID" displayName:@"Temp Display Name" sessionMode:GKSessionModeClient];

and I found that I wasn't calling release anywhere in my code. My questions are...

  1. Is this a memory leak?
  2. If so, what are some reasons that Instruments might not catch it?

My obvious concern is that I have memory leaks in my code and Instruments isn't catching them.

Thanks so much in advance for your help!

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

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

发布评论

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

评论(2

水溶 2024-09-18 15:32:47

动态分配的内存有多种类型。

  1. 带有引用计数的内存
    大于零,仍然被引用并且正在使用。

  2. 带有引用计数的内存
    仍被引用且仍在使用的零。

  3. 引用计数大于零的内存未被引用。

  4. 引用计数为零且未被引用的内存。

  5. 带有引用计数的内存
    大于零,仍被引用且未使用。

类型一是正常使用内存。第二类是一个错误,当您尝试遵循参考文献时,该错误将被报告为非法访问。类型 3 是仪器检测到的泄漏类型。类型 4 应由内存系统释放。

5 型是仪器无法检测到的泄漏,也不会被完整的垃圾收集器处理。这就是你似乎拥有的。

编辑:

我忘记了类型 6——引用计数与实际引用数量不匹配的内存。这可能最终会变成类型 2 或类型 4。

There are multiple types of dynamically allocated memory.

  1. Memory with a reference count
    greater than zero which is still referenced and is in use.

  2. Memory with a reference count
    of zero which is still referenced and is still in use.

  3. Memory with a reference count greater than zero which is not referenced.

  4. Memory with a reference count of zero which is not referenced.

  5. Memory with a reference count
    greater than zero which is still referenced and is NOT in use.

Type one is normal in use memory. Type two is a bug that will be reported as an illegal access when you try to follow the reference. Type 3 is the type of leak that instruments detects. Type 4 should be freed by the memory system.

Type 5 is a leak which cannot be detected by instruments, and will also not be handled by a full garbage collector. This is what you seem to have.

EDIT:

I forgot type 6 -- Memory with a reference count that doesn't match the number of actual references. This will probably eventually turn into type 2 or 4.

韶华倾负 2024-09-18 15:32:47

#1 的答案是“也许”...如果您的视图控制器从堆栈中弹出,并且没有其他人保留它,那么您的视图控制器应该被释放。 但是,(这可能是你的问题#2的答案)我最初犯的错误之一是不明白当你调用pushViewController时:导航控制器将保留你的视图控制器,所以你不需要不必。确保在创建视图控制器并将其压入堆栈后释放视图控制器。

MyViewController * viewController = [[MyViewController alloc] init...];
[self.navigationController pushViewController:viewController];
[viewController release];

我相信,如果您在这种情况下忘记了发布调用,静态分析器会警告您……这就是静态分析器如此出色的原因之一。

如果您此时释放视图控制器,则保留计数将始终比应有的值高+1。

我注意到静态分析仪对于这些事情比仪器的泄漏工具更有用。 (例如,不会找到包含循环引用的“泄漏”...引用自身的两个泄漏对象不会出现,因为“引用”仍然存在于您的对象周围)。

所以目前你有一些类似的东西......

@interface MyClass : UIViewController
{
     GKSession * gkSession;
}

...

@end

在你的实现中你应该确保你在 dealloc 方法中释放你的 iVar :

@implementation MyClass

...

- (void)dealloc
{
     [super dealloc];

     if (gkSession) [gkSession release];
}
@end

The answer to #1 is "maybe"... if your view controller gets popped off the stack, and no one else has retained it, then your view controller should get deallocated. But, (and this may be the answer to your question #2) one of the mistakes I made originally was not understanding that when you call pushViewController: the navigation controller will retain your view controller, so you don't have to. Make sure you are releasing your view controller after you create it and push it on the stack.

MyViewController * viewController = [[MyViewController alloc] init...];
[self.navigationController pushViewController:viewController];
[viewController release];

I believe the static analyzer will warn you if you forget the release call in this situation... which is one reason the static analyzer is so great.

If you don't release the view controller at this point, your retain count will always be +1 higher than it should.

I've noticed the static analyzer is MUCH more useful for these things than the instruments' leak tool. (Which, for example, won't find a "leak" that includes circular references... two leaked objects that reference themselves don't show up because "a reference" is still around for your object).

So currently you have something along the lines of...

@interface MyClass : UIViewController
{
     GKSession * gkSession;
}

...

@end

in your implementation you should make sure you release your iVar in your dealloc method:

@implementation MyClass

...

- (void)dealloc
{
     [super dealloc];

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