【问题标题】:how to release a CF object object correctly?如何正确释放 CF 对象对象?
【发布时间】:2012-06-14 17:24:31
【问题描述】:

我有这个方法(别人写的!)

- (CGPDFDocumentRef)getPdf {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:@"myLocalFileName.pdf"];

    NSURL *pdfURL = [NSURL fileURLWithPath:pdfPath];

    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);

    return pdf;
}

现在,我运行了分析并收到三个内存泄漏警告:

Call to function 'CGPDFDocumentCreateWithURL' returns a Core Foundation object with a +1 retain count
Object returned to caller as an owning reference (single retain count transferred to caller)
Object leaked: object allocated and stored into 'pdf' is returned from a method whose name ('getPdf') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'.  This violates the naming convention rules given in the Memory Management Guide for Cocoa

有人可以告诉我这里需要/应该做什么吗?我知道我应该在 CF 函数名称中使用 create 或 copy 来 CFRelease 一切。我不明白的是如何释放 pdf 并且仍然能够在函数结束时返回它。 我错过了什么? 谢谢。

【问题讨论】:

    标签: objective-c ios memory-management core-foundation


    【解决方案1】:

    您需要如下所示的 clang 源注释 http://cocoasamurai.blogspot.com/2012/01/clang-source-annotations.html

        #import <AppKit/AppKit.h>
    @interface NSColor (CWNSColorAdditions)
    -(CGColorRef)cw_cgColor CF_RETURNS_RETAINED;
    @end
    

    【讨论】:

    • 我喜欢你的回答,它对我有帮助。
    • 非常好的答案!
    【解决方案2】:

    接收 pdf 的代码在完成后有责任 CFRelease 它。与 Cocoa 不同,CF 不支持自动释放,因此任何从 CF 函数返回的对象都是调用者拥有且必须处理的对象。

    这也是命名约定,那些返回 CF 对象的函数应该相应地命名为 createcopy

    【讨论】:

    • 谢谢。所以当最后返回 CGPDFDocumentRef 对象时,它的保留计数不会改变,对吧?它仍然是 1,调用者有责任将其设为 0(在使用完之后)
    【解决方案3】:

    由于您要返回在函数中创建的对象,因此应正确命名函数本身,以表明应该释放它返回的对象。

    您可以调用函数createPdfcopyPdf,而不是getPdf。这将告诉调用者它应该在完成后调用CFRelease,并满足Analyze的请求。

    【讨论】:

    • 很有趣,谢谢。所以我只是通过命名函数 createPdf 或 copyPdf “修复”内存泄漏警告?
    • copyPDFcreatePDF 都暗示该函数做了一些不同于它所做的事情。仅仅在与复制无关的函数中加上“复制”一词,不符合内存管理规则的精神。
    • 是的,我已将该函数重命名为 createPdf,但仍然收到相同的三个内存泄漏警告。
    • @Chuck,这可能是真的,这取决于这个函数的真正含义。看起来copyPdf 非常接近它的功能。
    • 即使你改变了函数的名字,你仍然需要在调用方释放对象(一旦你完成了pdf)
    【解决方案4】:
    - (CGPDFDocumentRef)getPdf {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    
        NSString *documentsDirectory = [paths objectAtIndex:0];
    
        NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:@"myLocalFileName.pdf"];
    
        NSURL *pdfURL = [NSURL fileURLWithPath:pdfPath];
    
        CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);
    
        return [pdf autorelease];
    }
    

    我认为这可以解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2010-11-02
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      相关资源
      最近更新 更多