Initialization of 'UnsafePointerUInt8' results in a dangling pointer
Since Swift 3 it's possible to simply initialize a Data
instance with an UInt8
array.
let sendBytes:[UInt8] = [0x0, 0x0, 0x5, 0x0]
let msgData = Data(sendBytes)
Initialization of 'UnsafeMutableRawPointer' results in a dangling pointer
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).
CMVideoFormatDescriptionCreateFromH264ParameterSets throw Initialization of 'UnsafePointerInt' results in a dangling pointer
When you find some error message like: Generic parameter 'R' could not be inferred
, there may be two possible reasons.
- There is some type-related error somewhere, so Swift cannot infer the actual type
R
in that context - The expression is a little more complex than Swift can infer the type
In case 1, you need to find where is the actual error causing the issue.
In case 2, you can add some explicit type annotations to help Swift infer the types.
Please try something like this:
var formatDesc: CMVideoFormatDescription?
func createH264FormatDescription(SPS sps: Array<UInt8>, PPS pps: Array<UInt8>) -> OSStatus {
if formatDesc != nil { formatDesc = nil }
let status = sps.withUnsafeBufferPointer { spsBP->OSStatus in //<- Specify return type explicitly.
pps.withUnsafeBufferPointer { ppsBP in
let paramSet = [spsBP.baseAddress!, ppsBP.baseAddress!]
let paramSizes = [spsBP.count, ppsBP.count]
return paramSet.withUnsafeBufferPointer { paramSetBP in
paramSizes.withUnsafeBufferPointer { paramSizesBP in
CMVideoFormatDescriptionCreateFromH264ParameterSets(allocator: kCFAllocatorDefault, parameterSetCount: 2, parameterSetPointers: paramSetBP.baseAddress!, parameterSetSizes: paramSizesBP.baseAddress!, nalUnitHeaderLength: 4, formatDescriptionOut: &formatDesc)
}
}
}
}
return status
}
UnsafeMutableBufferPointerAudioBuffer Speech To Text. Dangling Buffer Pointer
I am using the same AudioController
. I have found the solution here
Code can be updated like this:
let buffers = withUnsafeMutablePointer(to: &bufferList.mBuffers) {
UnsafeMutableBufferPointer(start: $0, count: Int(bufferList.mNumberBuffers))
}
...
...
// get the recorded samples
status = withUnsafeMutablePointer(to: &bufferList) {
AudioUnitRender(AudioController.sharedInstance.remoteIOUnit!,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
$0)
}
Works for me fine
What does `UnsafeMutablePointer.initialize()`actually do?
One reason you need initialize()
, and the only one as for now maybe, is
for ARC.
You'd better think with local scope variables, when seeing how ARC works:
func test() {
var refVar: RefType = initValue //<-(1)
//...
refVar = newValue //<-(2)
//...
//<-(3) just before exiting the loacl scope
}
For a usual assignment as (2), Swift generates some code like this:
swift_retain(_newValue)
swift_release(_refVar)
_refVar = _newValue
(Assume _refVar
and _newValue
are unmanaged pseudo vars.)
Retain
means incrementing the reference count by 1, and release
means decrementing the reference count by 1.
But, think what happens when the initial value assignment as at (1).
If the usual assignment code was generated, the code might crash at this line:
swift_release(_refVar)
because newly allocated region for a var may be filled with garbages, so swift_release(_refVar)
cannot be safely executed.
Filling the newly region with zero (null) and release
safely ignoring the null could be one solution, but it's sort of redundant and not effective.
So, Swift generates this sort of code for initial value assignment:
(for already retained values, if you know ownership model, owned by you.)
_refVar = _initValue
(for unretained values, meaning you have no ownership yet.)
swift_retain(_initValue)
_refVar = _initValue
This is initialize
.
No-releasing the garbage data, and assign an initial value, retaining it if needed.
(The above explanation of "usual assignment" is a little bit simplified, Swift omits swift_retain(_newValue)
when not needed.)
When exiting the local scope at (3), Swift just generates this sort of code:
swift_release(_refVar)
So, this is deinitialize
.
Of course, you know retaining and releasing are not needed for primitive types like Int
, so initialize
and deinitialize
may be donothing
for such types.
And when you define a value type which includes some reference type properties, Swift generates initialize
and deinitialize
procedures specialized for the type.
The local scope example works for the regions allocated on the stack, and initialize()
and deinitialize()
of UnsafeMutablePointer
works for the regions allocated in the heap.
And Swift is evolving so swift, that you might find another reason for needing initialize()
and deinitialize()
in the future, you'd better make it a habit to initialize()
and deinitialize()
all allocated UnsafeMutablePointer
s of any Pointee
types.
Related Topics
iOS Add Button to Widget Extension
No Such Module Iqkeyboardmanagerswift
How to Make a Phonegap App for iOS Without Mac
Does "Let _ = ..." (Let Underscore Equal) Have Any Use in Swift
Swift: Iboutlets Are Nil in Custom Cell
Restkit 0.20 JSON Mapping Along with Additional Offline Data
I Want to Draw Custom Shape Like Apple Shape on UIview
How to Get a Low Res Image, or Thumbnail from the Alassetrepresentation in Swift
Keep a UIview or UIviewcontroller on Top of All Others
Use Elcimagepickercontroller to Pick Video
iOS 11 CPU Throttling and Idle Timer
How to Use Pod in Notification Service Extension
How to Get HTML5 Video Thumbnail Without Using Poster on Safari or iOS
Why Use Corebluetooth Connectperipheral Did Not Call Delegate Methods in iOS8
Using Auto Layout to Have UIlabel and UItextfield Next to Each Other