Ios XCode-编写静态分析友好代码
我开始使用静态代码分析来发现代码中的内存管理问题。我发现它非常有用,但是我已经编写了一些代码,我确信这些代码不会导致内存泄漏(仪器不会报告任何泄漏),而是由分析仪报告的。我认为这是我以不友好的方式编写代码的问题。这里有一个例子Ios XCode-编写静态分析友好代码,ios,objective-c,xcode,Ios,Objective C,Xcode,我开始使用静态代码分析来发现代码中的内存管理问题。我发现它非常有用,但是我已经编写了一些代码,我确信这些代码不会导致内存泄漏(仪器不会报告任何泄漏),而是由分析仪报告的。我认为这是我以不友好的方式编写代码的问题。这里有一个例子 for (glyphUnit *ellipsisDot in ellipsisArray) { CGPathRef newDot = CGPathCreateCopyByTransformingPath(ellipsisDot.glyphPath, &el
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
,自定义类在其dealoc
方法中释放该属性。因此,在这个循环中,我将转换路径并将其存储在一个newDot
中,然后释放原始glyphPath,以便将新创建的路径分配给它。我可以看出这是如何让代码分析器感到困惑的,它给出了一个消息,我正在减少一个我不拥有的对象。在新路径中是否有另一种不混淆的交换方式?应该是
for (glyphUnit *ellipsisDot in ellipsisArray) {
CGPathRef newDot = CGPathCreateCopyByTransformingPath(ellipsisDot.glyphPath, &ellipsisTransform);
ellipsisDot.glyphPath = newDot;
CGPathRelease(newDot);
}
您正在通过CG CreateCopy操作创建newDot
,并且需要对该变量执行release操作。因此,分析仪警告您不要拥有ellipsisDot.glyphPath
param来释放它。您试图在此处释放错误的参数。当您将该发布语句放在第二行时,ellipsisDot.glyphPath
和newDot
指向两个单独的实例。仅在第三行,您将newDot
分配给ellipsisDot.glyphPath
它应该是
for (glyphUnit *ellipsisDot in ellipsisArray) {
CGPathRef newDot = CGPathCreateCopyByTransformingPath(ellipsisDot.glyphPath, &ellipsisTransform);
ellipsisDot.glyphPath = newDot;
CGPathRelease(newDot);
}
您正在通过CG CreateCopy操作创建
newDot
,并且需要对该变量执行release操作。因此,分析仪警告您不要拥有ellipsisDot.glyphPath
param来释放它。您试图在此处释放错误的参数。当您将该发布语句放在第二行时,ellipsisDot.glyphPath
和newDot
指向两个单独的实例。仅在第三行,您将newDot
分配给ellipsisDot.glyphPath
结果是,我忘记了在自定义glyphUnit
类中定义setter。在对象的弧形世界里,用来合成我的方法,我忘记了需要管理我的保留基础的核心基础。我在我的dealloc
中发布了glyphPath,但没有使用setter方法。正如@Sven所怀疑的,我只是简单地使用了一个合成的assign
,并通过在上面的代码片段中进行一些不太直观的发布来弥补setter方法的不足。现在,我在glyphUnit中添加了一个setter方法,如下所示
- (void)setGlyphPath:(CGPathRef)newPath
{
if (_glyphPath != newPath)
{
CGPathRelease(_glyphPath);
_glyphPath = CGPathRetain(newPath);
}
}
添加了这个之后,我现在有了必要的保留,可以将我的代码片段更改为@ACB描述的代码片段,并且我的代码运行得很好(没有它,显然会导致EXC_BAD_访问)
感谢@Sven推断出我的错误并为我指明了正确的方向。。。没有双关语。事实证明,我忘记了在自定义的
glyphonunit
类中定义setter。在对象的弧形世界里,用来合成我的方法,我忘记了需要管理我的保留基础的核心基础。我在我的dealloc
中发布了glyphPath,但没有使用setter方法。正如@Sven所怀疑的,我只是简单地使用了一个合成的assign
,并通过在上面的代码片段中进行一些不太直观的发布来弥补setter方法的不足。现在,我在glyphUnit中添加了一个setter方法,如下所示
- (void)setGlyphPath:(CGPathRef)newPath
{
if (_glyphPath != newPath)
{
CGPathRelease(_glyphPath);
_glyphPath = CGPathRetain(newPath);
}
}
添加了这个之后,我现在有了必要的保留,可以将我的代码片段更改为@ACB描述的代码片段,并且我的代码运行得很好(没有它,显然会导致EXC_BAD_访问)
感谢@Sven推断出我的错误并为我指明了正确的方向。。。没有双关语。此代码是正确的,但只有当
glyphUnit
类在其setGlyphPath:
accessor方法中进行了正确的内存管理时才是正确的。如果glyphPath
属性被声明为assign
(我认为这是因为代码显然正在工作),那么这段代码可以正常工作。我不确定这一点,因为他正在使用cgpathlease(ellipsisDot.glyphPath)代码>在第三行之前。@Sven您是对的,我使用的是'assign,所以它起作用了,我没有合适的setter方法。在对象世界中使用ARC使我忘记了访问器方法@谢谢您的回复,我将添加一个总结我的错误的答案。@user524261,那么上面的答案没有解决它吗?理想情况下,您的问题应该在此更改后得到解决。如果需要,您需要修改assign语句。在这种情况下,如果有帮助,请接受它好吗?谢谢。这段代码是正确的,但前提是glyphUnit
类在其setGlyphPath:
accessor方法中进行了正确的内存管理。如果glyphPath
属性被声明为assign
(我认为这是因为代码显然正在工作),那么这段代码可以正常工作。我不确定这一点,因为他正在使用cgpathlease(ellipsisDot.glyphPath)代码>在第三行之前。@Sven您是对的,我使用的是'assign,所以它起作用了,我没有合适的setter方法。在对象世界中使用ARC使我忘记了访问器方法@谢谢您的回复,我将添加一个总结我的错误的答案。@user524261,那么上面的答案没有解决它吗?理想情况下,您的问题应该在此更改后得到解决。如果需要,您需要修改assign语句。在这种情况下,如果有帮助,请接受它好吗?谢谢