methodSignatureForSelector 内存泄漏
Memory leak on methodSignatureForSelector
当我使用 instruments 分配工具分析世代时,我有以下代码会泄漏。
SEL sel = NSSelectorFromString(self.selector);
NSInvocation* invocation = [ NSInvocation invocationWithMethodSignature:[ self.target methodSignatureForSelector:sel ] ];
[ invocation setTarget:self.target ];
[ invocation setSelector:sel ];
[ invocation invoke ];
代码不检查 return 值。有一些调用会 return 对象,但这些调用被简单地忽略了。
泄漏指向 [ NSMethodSignature methodSignatureForSelector] 的调用。堆栈显示此函数中的 calloc 调用泄漏了 48 个字节。
因为,我正在使用 ARC,我的假设是这些缓冲区将被自动垃圾收集。然而还是有漏洞。分配工具中最接近堆栈顶部的最后一个符号函数是
+[ NSMethodSignature signatureWithObjCTypes ]
这些在代码执行期间被调用了数千次,并且泄漏正在堆积。任何有助于追踪此问题的帮助将不胜感激。
我的流程:
我使用了 Instruments - Allocations,检查了引用计数,然后 运行 两代。 Allocations 工具允许您向下钻取到一代,然后选择一个在生成期间分配(而不是释放)的缓冲区,然后您可以向下钻取到缓冲区查看其引用计数历史记录。如果最后一个条目有引用计数,那么你可能有泄漏。现在只需要推断是否存在导致该对象泄漏的强循环。
编译器抱怨内存泄漏,但如果选择器 returns 无效,则您不会在此处泄漏内存。看看这个 discussion
尝试使用这个:
[self.target performSelector:sel object:nil afterDelay:0.0];
正如@Basheer_CAD 引用的线程中所建议的那样,我将所有 returning 对象的 NSInvocations 更改为现在 return void。但这对泄漏没有影响。此外,分配工具似乎明确指出 methodForSignature 是罪魁祸首,而不是调用的 return 值。然后,我决定再 运行 几代,现在明显泄漏变少了。第三代就没有漏水了。所以看起来这次泄漏与NSInvocation 是否有returned 对象无关。看起来 methodSignatureForSelector 正在分配一个 48 字节的缓冲区,并且这个缓冲区是针对 Class 对象缓存的。缓存可能服务于对相同方法签名的重复调用。我将忽略此泄漏,因为它不会在几代之后出现,并将其计入某种缓存构建。
因此,如果这些泄漏出现,解决它的最佳方法是 运行 多几代,直到它不再出现。
当我使用 instruments 分配工具分析世代时,我有以下代码会泄漏。
SEL sel = NSSelectorFromString(self.selector);
NSInvocation* invocation = [ NSInvocation invocationWithMethodSignature:[ self.target methodSignatureForSelector:sel ] ];
[ invocation setTarget:self.target ];
[ invocation setSelector:sel ];
[ invocation invoke ];
代码不检查 return 值。有一些调用会 return 对象,但这些调用被简单地忽略了。
泄漏指向 [ NSMethodSignature methodSignatureForSelector] 的调用。堆栈显示此函数中的 calloc 调用泄漏了 48 个字节。
因为,我正在使用 ARC,我的假设是这些缓冲区将被自动垃圾收集。然而还是有漏洞。分配工具中最接近堆栈顶部的最后一个符号函数是
+[ NSMethodSignature signatureWithObjCTypes ]
这些在代码执行期间被调用了数千次,并且泄漏正在堆积。任何有助于追踪此问题的帮助将不胜感激。
我的流程: 我使用了 Instruments - Allocations,检查了引用计数,然后 运行 两代。 Allocations 工具允许您向下钻取到一代,然后选择一个在生成期间分配(而不是释放)的缓冲区,然后您可以向下钻取到缓冲区查看其引用计数历史记录。如果最后一个条目有引用计数,那么你可能有泄漏。现在只需要推断是否存在导致该对象泄漏的强循环。
编译器抱怨内存泄漏,但如果选择器 returns 无效,则您不会在此处泄漏内存。看看这个 discussion
尝试使用这个:
[self.target performSelector:sel object:nil afterDelay:0.0];
正如@Basheer_CAD 引用的线程中所建议的那样,我将所有 returning 对象的 NSInvocations 更改为现在 return void。但这对泄漏没有影响。此外,分配工具似乎明确指出 methodForSignature 是罪魁祸首,而不是调用的 return 值。然后,我决定再 运行 几代,现在明显泄漏变少了。第三代就没有漏水了。所以看起来这次泄漏与NSInvocation 是否有returned 对象无关。看起来 methodSignatureForSelector 正在分配一个 48 字节的缓冲区,并且这个缓冲区是针对 Class 对象缓存的。缓存可能服务于对相同方法签名的重复调用。我将忽略此泄漏,因为它不会在几代之后出现,并将其计入某种缓存构建。 因此,如果这些泄漏出现,解决它的最佳方法是 运行 多几代,直到它不再出现。