This is an article I translated early last year, published in Jane’s Book, and now published in Nuggets, as part of the reference count series.
I came across this document, so WRITE it down. When we use the Core Foundation API in our APP, to avoid memory leaks, we should follow the rules of Core Foundation when acquiring objects or creating objects.
basis
When using Core Foundation, Ownership Policy not only helps us understand memory management, but also helps us understand the Ownership of objects. An object may have more than one owner and relies on a retain count to keep track of the number of owners. Once the reference count reaches zero (there is no owner), the object is released. Core Foundation specifies the following three rules for creating and manipulating objects.
- If you create the object (either directly or indirectly by copying an existing object), you own it.
- If you get an object from somewhere else, you *** don’t *** own the object, so to avoid the object being freed, you can use
CFRetain
The reference count +1 becomes the owner of the object. - If you are the owner of the object, you must use it after using it
CFRelease
Function to remove ownership, otherwise causing a memory leak.
Common naming
When you’re using Core Foundation, there’s a lot of ways to refer to an object. According to the Ownership Policy of Core Foundation, you need to know if the object returned by calling the function is owned by you so that you can perform the corresponding memory management operation. Simply put, if a function’s function name contains Create or Copy, you own the object that the function returns. If the function name contains Get, you do not own the returned object. The Create Rule and The Get Rule explain this naming in great detail.
Important :Cocoa provides a very similar nomenclature for memory management. The naming of Core Foundation functions, especially functions with 'Create' in their names, is used only for C functions that return Core Foundation objects. The naming of objective-C methods is governed by Cocoa, whether methods return Cocoa objects or Core Foundation objects.Copy the code
Create rules
The Core Foundation function name contains the following name to indicate that you own the object returned by the function:
- Contains in the function name
Create
This is a function that creates an object; - Contains in the function name
Copy
This is a function that copies an existing object. If you own the object, then you are relieved of responsibility and ownership of the object when you finish using itCFRelease
Function). Consider the following example. The first example shows two sumsCFTimeZone
Related to creating functions as well as an andCFBundle
About the create function.
CFTimeZoneRef CFTimeZoneCreateWithTimeIntervalFromGMT (CFAllocatorRef allocator, CFTimeInterval ti);
CFDictionaryRef CFTimeZoneCopyAbbreviationDictionary (void);
CFBundleRef CFBundleCreate (CFAllocatorRef allocator, CFURLRef bundleURL);
Copy the code
The first function, whose name contains Create, returns a newly created CFTimeZone object. You own the object, and it’s your responsibility to rescind ownership when you’re done with it. The second function, whose name contains Copy, creates a Copy of the CFTimeZone object’s properties (note that this function is different from the one that gets the CFTimeZone object’s properties). Of course, you own the object, too. The third function also contains Create, although it may return an existing CFBundle object. When returning an existing CFBundle object, the object retains Count+1 and you still own the object, so it is your responsibility to revoke ownership when you are done using it. The following example may be a bit complicated, but follow a simple rule.
/* from CFBag.h */
CF_EXPORT CFBagRef CFBagCreate(CFAllocatorRef allocator, const void **values, CFIndex numValues, const CFBagCallBacks *callBacks);
CF_EXPORT CFMutableBagRef CFBagCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFBagRef bag);
Copy the code
The CFBag function CFBagCreateMutableCopy has both Create and Copy in its name. It is a Create function because the function name contains Create. Note that the first argument is of type CFAllocatorRef, which is a good indication of this. The Copy function describes calling the CFBagRef parameter and creating a Copy of it. It also indicates what happens to the element objects in the source collection (Bag is a collection data type) : they are copied into the newly created Bag collection. The secondary Copy and NoCopy in function names indicate how objects owned by the source object are treated: copied or not. For example, the elements in the Bag object are copied in CFBagCreateMutableCopy.
Access rules
If you call a Core Foundation function in addition to Create and Copy and Get an object, like Get, you don’t own the object, so you don’t know how long the object has lived. If you want the pillow to stay with the object for the duration of use, you must claim ownership. So it’s your responsibility to revoke ownership when you’re done with this object. Thinking CFAttributedStringGetString function, rich text string string objects.
CFStringRef CFAttributedStringGetString (CFAttributedStringRef aStr);
Copy the code
If the rich text string object as an argument is freed, then the returned string object is released. If the returned string object has only one owner, then the string object is freed. If you want to use a string object after the rich text string object has been freed, you must declare ownership. So it is your responsibility to revoke ownership of the object when you are done with it, otherwise it will cause a memory leak.
Instance variables and pass parameters
Normally, when one object is passed as a parameter to another object (that is, when the receiver’s member attribute is assigned to a parameter object), the receiver takes ownership of the parameter object if it needs to preserve its life. When a function receives an object as a parameter, the original receiver does not own the parameter object, so the parameter object may be released at any time unless the receiver claims ownership. When the receiver is assigned a new value or released, it is the receiver’s responsibility to revoke ownership of the parameter object.
Examples of ownership
To avoid runtime errors or memory leaks, you should always apply Ownership Policy whether Core Foundation objects are received (receiving object member variable assignments), passed (as parameters), or returned (as return values). To understand why you need to claim ownership of an object that you didn’t create, consider the following example. Suppose you just get a value from an object that it owns, and then the object is released. If the owner of the object is the only one, then the value is released because it has no owner. Now you’re referencing an empty object, and when you use that empty object, your APP will crash.
Here are three code blocks: the set function, the get function, and a function that strongly references Core Foundation objects until certain conditions are met:
static CFStringRef title = (__bridge CFStringRef)@"abc";
void SetTitle(CFStringRef newTitle) {
CFStringRef temp = title;
title = CFStringCreateCopy(kCFAllocatorDefault , newTitle); // retainCount+1
CFRelease(temp);
}
Copy the code
The above example uses a static CFStringRef variable to retain the retained CFString object. You can also store the object in other ways, but you must place the object outside the scope of the receiver function. The function assigns the title object to the local variable temp, then copies the newTitle object and frees the temp(old title) object. The function is released after the copy in case newTitle and the static variable title are passed in as an object. Note that the newTitle object passed in is not just a retain, it is also copied (recall that Copy and retain are equivalent from an ownership perspective). The reason for using Copy is that the newTitle argument does not want to change during the execution of the function. Even if the argument is of type CFStringRef, it is still possible to point to a CFMutableStringRef object (the parent class pointer points to a subclass object). So by copying this parameter object, you get an immutable object. If you want to get an immutable object, you should copy the argument object. If you just want to keep the returned object, use Retain.
The get function is simpler:
CFStringRef GetTitle() {
return title;
}
Copy the code
Simply returning the object will weakly reference the object. In other words, the pointer to the object is simply copied by the receiver’s variable, but the reference count does not change. The same goes for getting elements from collections.
The following functions retain the object retrieved from the collection until it is no longer needed. Suppose this object is *** immutable ***.
static CFStringRef title = NULL;
void MyFunction(CFDictionaryRef dict, Boolean aFlag) {
if(! title && ! aFlag) { title = (CFStringRef)CFDictionaryGetValue(dict, CFSTR(" title ")); title =CFRetain(title);
}
/* Do something with title here. */
if (aFlag) {
CFRelease(title); }}Copy the code
The following example shows passing a number object from an array. The array callback (kCFTypeArrayCallBacks) indicates that objects added to the array are retained, so the Number object can be released after being added to the array.
float myFloat = 10.523987;
CFNumberRef myNumber = CFNumberCreate(kCFAllocatorDefault,
kCFNumberFloatType, &myFloat);
CFMutableArrayRef myArray = CFArrayCreateMutable(kCFAllocatorDefault, 2, &kCFTypeArrayCallBacks);
CFArrayAppendValue(myArray, myNumber);
CFRelease(myNumber);
// code continues...
Copy the code
Note that there is a potential pitfall in the following example, which is to use the elements in the array even after you Release them:
CFRelease(myArray);
CFNumberRef otherNumber = // ... ;
CFComparisonResult comparison = CFNumberCompare(myNumber, otherNumber, NULL);
Copy the code
Unless you Retain the number element or array, or assign the number element or array to another object that has ownership of the number element or array. If none of the above conditions are met, the array or number element has no owner and is released. CFNumberCompare will crash when using the freed object.
As a fresh graduate students, a lot of things are in their own groping, please your predecessors more advice ~