I am using a variable inside a function with holds and UnsafeMutablePointer<objc_property_t>. Should I call free on it?
func logProps() {
var count: UInt32 = 0
let _propArr = class_copyPropertyList(cls, &count)
// ...
// free(propArr) // ?
}
On a different note, is free same as using deallocate (Swift UnsafeMutablePointer: Must I call deinitialize before deallocate?) ?
Yes, because of the name of the method. class_copyPropertyList includes the word "copy" which indicates that the buffer belongs to you. Note that the documentation also indicates this:
You must free the array with free().
So you should use free() to destroy this buffer. This is currently identical to calling .deallocate(), but that is not promised, so follow the instructions as given.
(Thanks to MartinR for running down the question of free vs deallocate.)
Related
I was doing some research on mutexes and came across the following Swift code:
class Lock {
private var mutex: pthread_mutex_t = {
var mutex = pthread_mutex_t()
pthread_mutex_init(&mutex, nil)
return mutex
}()
func someFunc() {
pthread_mutex_lock(&mutex)
defer { pthread_mutex_unlock(&mutex) }
...
}
}
The code defines and initializes a pthread_mutex_t within the closure, then assigns the returned value to a class property. It then lock and unlocks within several of the functions as shown.
Since one should also call pthread_mutex_destroy, it implies that some sort of allocation is occurring within the mutex which may or may not reference the address of the original value.
In effect, the mutex is initialized in one place and stored in another.
The question is whether or not it's safe or correct to do this?
What if the mutex initializer needed arguments?
private var mutex: pthread_mutex_t = {
var recursiveMutex = pthread_mutex_t()
var recursiveMutexAttr = pthread_mutexattr_t()
pthread_mutexattr_init(&recursiveMutexAttr)
pthread_mutexattr_settype(&recursiveMutexAttr, PTHREAD_MUTEX_RECURSIVE)
pthread_mutex_init(&recursiveMutex, &recursiveMutexAttr)
return recursiveMutex
}()
The later strikes me as definitely being incorrect, as the attribute storage whose address is passed into the mutex will disappear when the closure collapses.
It's not, this code is broken.
To work, the pthread_mutex_t would need to be initialized in-place within a class instance, and never copied out. The class would need to expose lock/unlock methods which operator on the instance-variable in-place.
Value Types
Note that pthread_mutex_t, pthread_rwlock_t, and os_unfair_lock are value types, not reference types. That means that if you use = on them, you make a copy. This is important, because these types can't be copied! If you copy one of the pthread types, the copy will be unusable and may crash when you try to use it.
– By Mike Ash, Friday Q&A 2017-10-27: Locks, Thread Safety, and Swift: 2017 Edition
Check out https://cocoawithlove.com/blog/2016/06/02/threads-and-mutexes.html
And this example usage of pthread_mutex_t in Swift: https://github.com/mattgallagher/CwlUtils/blob/0bfc4587d01cfc796b6c7e118fc631333dd8ab33/Sources/CwlUtils/CwlMutex.swift#L60-L105
Since Xcode 11.4 I get the warning message "Initialization of 'UnsafeMutableRawPointer' results in a dangling pointer"
for the following code where I read an SIMD4 from an MTLTexture into an array:
let texArray = Array<SIMD4<Float>>(repeating: SIMD4<Float>(repeating: 0), count: 1)
texture.getBytes(UnsafeMutableRawPointer(mutating: texArray), bytesPerRow: (MemoryLayout<SIMD4<Float>>.size * texture.width), from: region, mipmapLevel: 0)
Can somebody figure out how to create the array pointer to get rid of the warning ?
Thanks
TLDR
make text array mutable (use var instead of let) and use withUnsafeMutableBytes
var texArray = Array<SIMD4<Float>>(repeating: SIMD4<Float>(repeating: 0), count: 1)
texArray.withUnsafeMutableBytes { texArrayPtr in
texture.getBytes(texArrayPtr.baseAddress!, bytesPerRow: (MemoryLayout<SIMD4<Float>>.size * texture.width), from: region, mipmapLevel: 0)
}
Explanation
The warning was introduced because the compiler can't make sure that data backing the pointer will not be deallocated. Consider you have a function (e.g. implemented in C) manipulating some data pointed to.
func f(_ a: UnsafeMutablePointer<Int>){
a[0] = 42
}
Then it must be made sure that memory was not deallocated until the end of the call. So when calling this function in the following way it is not safe
var a: = [1]
p: UnsafeMutablePointer<Int>(&a)
// at this point the compiler may optimise and deallocate 'a' since it is not used anymore
f(p)
Currently this won't be an issue as far as I know since local variables will not be deallocated before the end of the scope.
One can illustrate the possible issue by introducing a nested scope in the following way
var p: UnsafeMutablePointer<Int>?
do {
var a = [1]
p = UnsafeMutablePointer<Int>(&a)
} // "a" will be deallocated here
// now "p" is a dangling pointer the compiler warned you of
var b = [0] // compiler will use same memory as for "a", so manipulating memory of "p" won't segfault
f(p!) // manipulate memory
print(b[0]) // prints 42 although "b" was initialised to 0
Due to the fact that b allocates the same memory that a was using before, the memory of b is modified by the call to f(p!). So b[0] is 42 although it was initialised to 0 and not explicitly modified.
With this illustration it should become clear why there are methods withUnsafeMutableBytes and withUnsafeMutableBufferPointer on Swift arrays and global functions withUnsafeMutablePointer plus immutable variants. (I personally find it confusing that methods must be used on arrays and and global functions on structs.)
These functions make sure that memory is not deallocated (or reused) for the scope of the closure (I also created gist with some examples).
I've been saying this to form a C array of CGPoint:
let arr = UnsafeMutablePointer<CGPoint>.allocate(capacity:4)
defer {
arr.deinitialize()
arr.deallocate(capacity:4)
}
arr[0] = CGPoint(x:0,y:0)
arr[1] = CGPoint(x:50,y:50)
arr[2] = CGPoint(x:50,y:50)
arr[3] = CGPoint(x:0,y:100)
Now (Swift 4.1 in the Xcode 9.3 beta) both deinitialize and deallocate(capacity:) are deprecated. It looks like what I'm supposed to say now might be:
defer {
arr.deinitialize(count:4)
arr.deallocate()
}
Is that right?
Yes, that is part of SE-0184 Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size,
which has been implemented in Swift 4.1.
In particular:
Removing capacity from deallocate(capacity:) will end the confusion over what deallocate() does, making it obvious that deallocate() will free the entire memory block at self, just as if free() were called on it.
The old deallocate(capacity:) method should be marked as deprecated and eventually removed since it currently encourages dangerously incorrect code.
Could anyone please explain or give a link to a good guide on UnsafeMutablePointers? I can't freaking understand how they work and how to modify them.
Here's an example.
I am migrating my custom video player to Swift from Objective-C.
In Objective-C I create MTAudioProcessingTapRef using a callbacks structure:
MTAudioProcessingTapCallbacks callbacks;
callbacks.clientInfo = (__bridge void *)(self);
callbacks.init = initTap;
// Init other fields of callbacks
MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PostEffects, &tap);
Here I cast retainable MyClass pointer to void pointer to use it as clientInfo later.
(__bridge T) op casts the operand to the destination type T. If T is a
non-retainable pointer type, then op must have a retainable object
pointer type.
Then tap gets initialized:
void initTap(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut)
{
*tapStorageOut = clientInfo;
}
Here I pass a pointer to self into tapStorageOut to grab self inside tap's callback function.
And then processing is performed:
void processTap(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut,
CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut)
{
MyClass *self = (__bridge MyClass *) MTAudioProcessingTapGetStorage(tap);
MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, flagsOut, NULL, numberFramesOut);
}
Now I have a few issues here.
I did found how to cast types into other types. Here are the functions:
func bridge<type : AnyObject>(object : type) -> UnsafeRawPointer
{
let unmanagedObject : Unmanaged = Unmanaged.passUnretained(object)
let unsafeMutableRawObject : UnsafeMutableRawPointer = unmanagedObject.toOpaque()
return UnsafeRawPointer(unsafeMutableRawObject)
}
func bridge<type : AnyObject>(pointer : UnsafeRawPointer) -> type
{
let unmanagedObject : Unmanaged<type> = Unmanaged<type>.fromOpaque(pointer)
let object : type = unmanagedObject.takeUnretainedValue()
return object
}
but I have zero understanding of what all of these letters do. Some explanation of this by one of you guys would be awesome.
Let's look at initTap function. Here I have a pointer A (tapStorageOut) that references a pointer B that references some data. I change pointer B to pointer C, which is my clientInfo. Clear as a sunny day.
Now, in Swift tapStorageOut is UnsafeMutablePointer now, whatever that thing is. And I have zero clue about how to deal with it.
In Objective-C when I process data I have a bufferListInOut variable which is a pointer to AudioBufferList structure.
In Swift however it has UnsafeMutablePointer type. So again, not understanding how UnsafeMutablePointers work prevents me from grabbing the data.
The main use of a pointer in Swift is working with C API and such. For the most part you should use reference semantics instead of pointers in Swift. That means using a class, when you pass a class instance around it automatically passes a reference instead of making a copy. Thus, it saves resources and any changes you make to a reference to the instance are reflected everywhere it is referenced. A Swift class is generally instantiated on the heap.
When you convert Objective-C to Swift pointers to objects are generally treated as references to those objects. Internally, a Swift reference is pretty much semantic sugar for a pointer.
Swift structures, on the other hand, have value semantics. They are generally instantiated on the stack and when you pass them around they are copied rather than passing a reference. The same goes when you mutate them, a new instance is created with the new values and it is swapped for the old instance. There are some tricks done where a struct will wrap a block of memory and hold a pointer to that memory. Thus a struct may have some reference semantics internally but try to avoid breaking the expectation of a struct's value being copied when it's passed around.
Some good reading:
Fundamentals of Callbacks for Swift Developers
Thinking in Swift, Part 3: Struct vs. Class
Lazy Initialization with Swift
I'd read these and take a good, hard look at your architecture before trying to use stuff like UnsafeMutablePointer. Yes, they are useful in some circumstances but they can be a pain to work with and are not necessary for most pure Swift tasks. Especially in a Swift API!
I'm working, tentatively, with the AudioToolbox API using Swift 2.0 and Xcode 7b6. The API uses a lot of c-language constructs, including function pointers. This is my first time working with commands like withUnsafeMutablePointer and unsafeBitCast. I am looking for a reality check to make sure that I am not way off base in what I am doing.
For example, to open a file stream, you use the following function:
func AudioFileStreamOpen(
_ inClientData: UnsafeMutablePointer<Void>
, _ inPropertyListenerProc: AudioFileStream_PropertyListenerProc
, _ inPacketsProc: AudioFileStream_PacketsProc
, _ inFileTypeHint: AudioFileTypeID
, _ outAudioFileStream: UnsafeMutablePointer<AudioFileStreamID>) -> OSStatus
Just the type signature of the function makes me start to sweat.
At any rate, the inClientData parameter needs to be an UnsafeMutablePointer<Void>, and the pointer will point to an instance of the same class I am working in. In other words, it needs to be a pointer to self. My approach is to call the function using withUnsafeMutablePointer like this:
var proxy = self
let status = withUnsafeMutablePointer(&proxy) {
AudioFileStreamOpen($0, AudioFileStreamPropertyListener
, AudioFileStreamPacketsListener, 0, &audioFileStreamID)
}
My first question is whether or not I'm using withUnsafeMutablePointer correctly here. I wasn't sure how to get a pointer to self - just writing &self doesn't work, because self is immutable. So I declared proxy as a variable and passed a reference to that, instead. I don't know if this will work or not, but it was the best idea I came up with.
Next, AudioFileStreamPropertyListener and AudioFileStreamPacketsListener are C callback functions. They each get passed the pointer to self that I created using withUnsafeMutablePointer in AudioFileStreamOpen. The pointer is passed in as an UnsafeMutablePointer<Void>, and I need to cast it back to the type of my class (AudioFileStream). To do that, I believe I need to use unsafeBitCast. For example, here is AudioFileStreamPropertyListener:
let AudioFileStreamPropertyListener: AudioFileStream_PropertyListenerProc
= { inClientData, inAudioFileStreamID, inPropertyID, ioFlags in
let audioFileStream = unsafeBitCast(inClientData, AudioFileStream.self)
audioFileStream.didChangeProperty(inPropertyID, flags: ioFlags)
}
That compiles fine, but again I'm not sure if I'm using unsafeBitCast correctly, or if that is even the correct function to be using in this kind of situation. So, is unsafeBitCast the correct way to take an UnsafeMutablePointer<Void> and cast it to a type that you can actually use inside of a C function pointer?
It's interesting that the inClientData "context" param is bridged as UnsafeMutablePointer, since I doubt the AudioToolbox APIs will modify your data. It seems it would be more appropriate if they'd used COpaquePointer. Might want to file a bug.
I think your use of withUnsafeMutablePointer is wrong. The pointer ($0) will be the address of the variable proxy, not the address of your instance. (You could say $0.memory = [a new instance] to change it out for a different instance, for example. This is a bit confusing because its type is UnsafeMutablePointer<MyClass> — and in Swift, the class type is itself a pointer/reference type.)
I was going to recommend you use Unmanaged / COpaquePointer, but I tested it, and realized this does exactly the same thing as unsafeAddressOf(self)!
These are equivalent:
let data = UnsafeMutablePointer<Void>(Unmanaged.passUnretained(self).toOpaque())
let data = unsafeAddressOf(self)
And these are equivalent:
let obj = Unmanaged<MyClass>.fromOpaque(COpaquePointer(data)).takeUnretainedValue()
let obj = unsafeBitCast(data, MyClass.self)
While the Unmanaged approach makes logical sense, I think you can see why it might be prefereable to use unsafeAddressOf/unsafeBitCast :-)
Or, you might consider an extension on Unmanaged for your own convenience:
extension Unmanaged
{
func toVoidPointer() -> UnsafeMutablePointer<Void> {
return UnsafeMutablePointer<Void>(toOpaque())
}
static func fromVoidPointer(value: UnsafeMutablePointer<Void>) -> Unmanaged<Instance> {
return fromOpaque(COpaquePointer(value))
}
}
Then you can use:
let data = Unmanaged.passUnretained(self).toVoidPointer()
let obj = Unmanaged<MyClass>.fromVoidPointer(data).takeUnretainedValue()
Of course, you will need to ensure that your object is being retained for the duration that you expect it to be valid in callbacks. You could use passRetained, but I would recommend having your top-level controller hold onto it.
See some related discussion at https://forums.developer.apple.com/thread/5134#15725.