Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
496 views
in Technique[技术] by (71.8m points)

objective c - How to properly handle CF objects created at the beginning of the program and deleted at the end

I put

I declared @property (nonatomic) ABAddressBookRef addressBook; as the property of the class extension

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter]removeObserver:self];

    CFRelease(self.addressBook);
}

Then in a function ONLY called by viewDidLoad, I add: -(void) vCreateAddressBookAndPopulateContact

{
    self.addressBook = ABAddressBookCreate(); //will be released at dealloc
    [self vPopulateContact];
}

It gives me warning: at allocation:

Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1

At deallocation:

Incorrect decrement of the reference count of an object that is not owned at this point by the caller

So, what should I do? How to tell that compiler that the object will be dereferenced latter at dealloc?

I wish I can move that ABAddressBookRef to ARC/NS land. But there is no way to do so.

self.addressBook cannot be released at the function. That's because if I want to add or remove

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(This is more a workaround, perhaps someone else has a better answer.)

The problem does not occur if you define addressBook not at as property but as an instance variable (perhaps in a class extension):

@interface YourClass () {
    ABAddressBookRef addressBook;
}

The problem with a property is that

self.addressBook = ABAddressBookCreate();
// ...
CFRelease(self.addressBook);

is translated to

[self setAddressBook:ABAddressBookCreate()];
// ...
CFRelease([self addressBook]);

so the static analyzer does not "see" at this point that the address book reference is preserved in some instance variable.

Remark: In dealloc, you should check that addressBook is not NULL

if (addressBook != NULL)
    CFRelease(addressBook);

to avoid a crash in the case that the variable has not been initialized in viewDidLoad.

Update: (Motivated by @11684's comment!) You could also keep your property, and use the associated instance variable for creation and release only:

_addressBook = ABAddressBookCreate();
// ...
if (_addressBook != nil)
    CFRelease(_addressBook);

In that case it would make sense to define the property as "read-only".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...