For a personal project, I have been writing some library to interface the CoreBluetooth API with the go language. Because of what it does, that library is written in objective-C with ARC disabled.
One function I had to write takes a memory buffer (allocated with malloc() on the go side), creates an NSData object out of it to pass the data to the writeValue:forCharacteristic:type: CoreBluetooth method, and then releases the NSData as well as the original memory buffer:
void Write(CBPeripheral *p, CBCharacteristic *c, void *bytes, int len) {
NSData *data = [NSData dataWithBytesNoCopy:bytes length:len freeWhenDone:true];
[p writeValue:data forCharacteristic:c type:CBCharacteristicWriteWithoutResponse];
[data release];
}
One thing I noticed is that the retainCount for data
increases during the writeValue:forCharacteristic:type: API call. It is 1 before, and 2 after. This is surprising to me, because the documentation says "This method copies the data passed into the data parameter, and you can dispose of it after the method returns."
I suspects this results in a memory leak. Am I missing something here ?
The issue here is this pairing:
NSData *data = [NSData dataWithBytesNoCopy:bytes length:len freeWhenDone:true];
…
[data release];
In manual retain-release you only call -release
if you’re responsible for the object, that is:
-
You retained the object.
-
You created a fresh object with an
+alloc
/-init
pair -
Or with
+new
-
You created a copy with
-copy
or related methods
In this case you’re not doing any of those. Rather, you’re calling a convenience method, +dataWithBytesNoCopy:length:freeWhenDone:
. This retains an autoreleased value, which isn’t something you need to release.
I touch on this in Objective-C Memory Management for Swift Programmers, but it’s also well covered by older documentation, like the How Memory Management Works section of Cocoa Fundamentals Guide.
The fix here is to either:
-
Switch to an
+alloc
/-init
pair. -
Stop calling
-release
.
I think the first is your best option because it’ll likely generates less autorelease pool traffic.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"