我开始使用静态代码分析来查找代码中的内存管理问题。我发现它非常有用,但是我写了几行代码,我确信它不会导致内存泄漏(仪器不会报告任何内容),但分析器会报告这些代码。我认为这是一个以非友好的方式编写代码的问题。这是一个例子
for (glyphUnit *ellipsisDot in ellipsisArray) {
CGPathRef newDot = CGPathCreateCopyByTransformingPath(ellipsisDot.glyphPath, &ellipsisTransform);
CGPathRelease(ellipsisDot.glyphPath); // Incorrect decrement of the reference count of an object that is not owned at this point by the caller
ellipsisDot.glyphPath = newDot;
}
其中glyphUnit
是一个简单的自定义类,其GCPathRef
作为属性,自定义类在其dealloc
方法中释放。所以在这个循环中,我正在转换路径并将其存储在newDot
中,然后释放原始的glyphPath,以便我可以为其分配新创建的路径。我可以看到这是如何使代码分析器混淆,它给出了一个消息,我正在递减一个我不拥有的对象。是否有另一种方式交换新路径而不会混淆它?
答案 0 :(得分:3)
应该是,
for (glyphUnit *ellipsisDot in ellipsisArray) {
CGPathRef newDot = CGPathCreateCopyByTransformingPath(ellipsisDot.glyphPath, &ellipsisTransform);
ellipsisDot.glyphPath = newDot;
CGPathRelease(newDot);
}
您正在通过CG CreateCopy操作创建newDot
,并且您需要对该变量进行释放。所以分析器警告你不要拥有ellipsisDot.glyphPath
param来释放它。你试图在这里发布错误的参数。当您将该发布语句放在第二行中时,ellipsisDot.glyphPath
和newDot
指向两个单独的实例。仅在第三行,您将newDot
分配给ellipsisDot.glyphPath
。
答案 1 :(得分:0)
事实证明,我忘了在自定义glyphUnit
课程中定义setter。在ARC世界中使用对象并用于合成我的方法我忘记了管理核心基础参考的保留计数的必要性。我一直在我的dealloc
中发布glyphPath,但没有使用setter方法。正如@Sven所怀疑的那样,我只是使用了一个合成的assign
,并通过在上面的代码片段中做一些不太直观的版本来弥补我的setter方法的不足。我现在已经在glyphUnit
- (void)setGlyphPath:(CGPathRef)newPath
{
if (_glyphPath != newPath)
{
CGPathRelease(_glyphPath);
_glyphPath = CGPathRetain(newPath);
}
}
添加之后,我现在已经有了必要的保留,可以将我的代码片段更改为所描述的@ACB,并且我的代码运行良好(没有它,显然会导致EXC_BAD_ACCESS)。
感谢@Sven推断我的错误并让我朝着正确的方向前进......没有任何双关语。