【问题标题】:Why is there a memory leak in GameCenterManager.m?为什么 GameCenterManager.m 中存在内存泄漏?
【发布时间】:2023-03-22 14:34:01
【问题描述】:

我在我的应用中使用 Game Center,发现 gamecentermanager.m 文件导致内存泄漏:

- (void) callDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err
{
assert([NSThread isMainThread]);
if([delegate respondsToSelector: selector])
{
    if(arg != NULL)
    {
        [delegate performSelector: selector withObject: arg withObject: err];
    }
    else
    {
        [delegate performSelector: selector withObject: err];
    }
}
else
{
    NSLog(@"Missed Method");
}
}

发生泄漏(根据编译器警告三角形)是因为 performSelector(两者)选择器是未知的。有两件事我想知道

1) 我直接从 Apple 网站上的示例中复制了这个,所以如果 Apple 构建它,代码不会出现错误吗?

2) 我该如何解决这个问题?

仅供参考,我正在使用 Xcode 4.3.1,使用 LLMV 编译器 3.1 和标准 (armv7) 架构。我也在使用 ARC。

如果您需要任何其他信息,请告诉我,并在此先感谢您。

【问题讨论】:

    标签: objective-c memory-leaks automatic-ref-counting selector game-center


    【解决方案1】:

    这里的问题是 ARC 无法判断您使用 -performSelector:withObject: 调用的方法的内存管理语义是什么。在 MRR 下,这无关紧要,因为调用代码应该相应地处理它(例如,如果它是一个拥有的对象,则通过释放返回值)。但在 ARC 下,编译器需要知道这些信息是正确的。我不记得 -performSelector:withObject: 的默认行为是什么,可能只是将其视为非拥有引用,在这种情况下,您实际上并没有泄漏。

    处理这种委托模式最简单的方法是仍然使用-respondsToSelector:,然后直接调用该方法,例如

    if ([_delegate respondsToSelector:@selector(foo:)]) {
        [_delegate foo:self];
    }
    

    在您的情况下,方法本身实际上并不知道选择器是什么。您最好的选择可能是完全放弃此方法,让其以前的调用者处理与代表的对话。

    【讨论】:

    • 难道不能在 NSObject 中添加一个“假”类别来声明这个方法吗?只是为了“阐明”语义......
    • @nielsbot:问题不在于缺少该方法的声明。问题是编译器甚至不知道他试图调用什么方法,不管声明如何,因为他使用动态选择器来调用它。
    • 因为你所说的,我决定不再使用我从 Apple 复制的 GameCenterManager 文件。谢谢你的回答。
    猜你喜欢
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 2015-08-04
    • 2016-08-03
    相关资源
    最近更新 更多