簡體   English   中英

釋放聲明為Objective-C屬性的C類型

[英]Releasing a C type declared as an Objective-C property

我已經聲明C類型為我的Objective-C對象的屬性。 我想確保我的財產正被ARC正確收集到垃圾。

僅僅重復幾次就不會泄漏內存,但是由於我還沒有找到關於該主題的適當文檔,因此我想確認一下。

基本上,當我覆蓋dealloc以釋放C類型時,出現錯誤,我的變量從未分配:

malloc:***對象錯誤:未分配要釋放的指針***
在malloc_error_break中設置一個斷點進行調試

@interface MyClass : NSObject
    @property (readonly, assign) xmlDocPtr doc;
@end

@implementation MyClass
    - (void)dealloc {
       if (_doc != NULL) {
          xmlFreeDoc(_doc);  // throwing da runtime error, see above!
       }
       NSLog(@"dealloc'ed!"); // call me please T___T
    }

    // Setting my C-type property here:
    - (instancetype)initWithFileAtPath:(NSString *)path {
       NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
       [self setDoc:htmlReadMemory([data bytes], (int)[data length], "", NULL, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR)];

       if (_doc == NULL) return nil;

       NSLog(@"init'ed!");  // gets called!
       return self;
    }

    // Property setter (as suggested by DarkDust):
    - (void)setDoc:(xmlDocPtr)doc {
       if (_doc != NULL) xmlFreeDoc(_doc);
       _doc = doc;
    }
@end

由於ARC只能對Objective-C對象進行操作,因此它無法幫助您管理C類型。

正確管理內存的關鍵問題始終是“誰'擁有'對象?” 在Objective-C中,這是使用引用計數和明確的命名規則來完成的。 由於C類型沒有此功能,因此需要小心。

那么,誰在創建您的xmlDoc實例? 如果與您為其編寫了dealloc方法的對象相同(讓我們調用該類Foo ),而您只想通過該屬性公開該實例,則所有權是明確的: Foo是實例的所有者,因此需要清除起來。 在這種情況下,您已經在dealloc中做到了(盡管那里有一個bug;變量本身總是有一個地址,所以&_doc永遠不會為NULL!)。 我將屬性設置為只讀,以避免任何人從外部弄亂指針(要對其進行分配,則需要直接訪問后備變量_doc )。 因此,它看起來像這樣:

@property(readonly, assign) xmlDocPtr doc;

...
_doc = CreateTheXMLDocInstance();
...

- (void)dealloc {
    if (_doc != NULL) xmlFreeDoc(_doc);
}

如果您實際上想使該屬性可寫,則需要正確處理設置器。 同樣,問題是:誰擁有實例? 如果您希望Foo對象成為唯一所有者,那么事情實際上就很容易了。 您只需要編寫一個自定義setter即可釋放舊實例:

- (void)setDoc:(xmlDocPtr)doc {
    // Do not free if it's the same pointer.
    if (doc == _doc) return;
    // Remove old instance, if we have one.
    if (_doc != NULL) xmlFreeDoc(_doc);
    // Assign new instance.
    _doc = doc;
}

如果Foo對象不是唯一所有者,則不允許在setter或dealloc取消分配_doc

現在,對於您的運行時錯誤,您在更新問題后已引用了該錯誤消息:錯誤消息告訴您某人正在嘗試釋放不是malloc返回值的地址。 很有可能,分配給_doc的值不是有效的指針,或者至少不是指向malloc返回的內存塊開頭的指針。 反過來,這意味着該錯誤必須在htmlReadMemory函數中的某個htmlReadMemory :它不會返回有效的xmlDocPtr

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM