Monday, August 31, 2026
HomeiOS DevelopmentUnsafe reminiscence pointers in Swift

Unsafe reminiscence pointers in Swift

[ad_1]

Learn to use uncooked pointer references, work together with unsafe pointers and manually handle reminiscence addresses in Swift.

Swift

Pointers in Swift

What’s is a pointer? A pointer is a variable that shops the reminiscence handle of a referenced object. As I discussed this in my earlier article, in regards to the reminiscence format of varied objects in Swift, a reminiscence handle is only a hexadecimal illustration of a knowledge situated someplace within the reminiscence. You employ situations of varied unsafe pointer sorts to entry information of a selected sort in reminiscence.

Why can we need to use these form of pointers on the first place? By default you do not have to write down unsafe Swift code, and in many of the circumstances you may stay with out unsafe reminiscence pointers. These pointers come useful if it’s a must to interoperate with different “unsafe” languages, similar to C. There are different low degree or legacy APIs that require the usage of guide reminiscence administration, however you should not be afraid, when you get conversant in unsafe Swift pointer sorts you will know much more about how reminiscence works and you may see how skinny is the layer between C libraries and Swift. 😱


What sort of pointers are there? To be able to perceive pointer sorts higher in Swift, let’s get again to C only for a second. Contemplate the next C code instance:




int predominant () {

    int x = 20;
    int* xPointer = &x;

    printf("x handle: `%p`n", &x);
    printf("x worth: `%u`n", x);
    printf("pointer handle: `%p`n", &xPointer);
    printf("pointer reference: `%p`n", xPointer); // equals the handle of x
    printf("pointer reference worth: `%u`n", *xPointer);

    *xPointer = 420;
    printf("x worth: `%u`n", x);
    printf("pointer reference worth: `%u`n", *xPointer);

    x = 69;
    printf("x worth: `%u`n", x);
    printf("pointer reference worth: `%u`n", *xPointer);

    return 0;
}

It can save you this code snippet utilizing the predominant.c title, then compile & run it utilizing the clang predominant.c -o predominant && ./predominant command. It’ll present a fairly similiar output.

$ clang predominant.c -o predominant && ./predominant
x handle: `0x16b0c7a38`
x worth: `20`
pointer handle: `0x16b0c7a30`
pointer reference: `0x16b0c7a38`
pointer reference worth: `20`
pointer worth `20`
tib@~: clang predominant.c -o predominant && ./predominant
x handle: `0x16d52fa38`
x worth: `20`
pointer handle: `0x16d52fa30`
pointer reference: `0x16d52fa38`
pointer reference worth: `20`
x worth: `420`
pointer reference worth: `420`
x worth: `69`
pointer reference worth: `69`


So what is going on on right here? Nicely, we merely created an integer variable and a pointer variable with an integer sort. We used the handle of our x variable (&x) to affiliate our pointer with the reminiscence handle of x. Now each variables factors to the identical reminiscence handle.

We are able to affirm this by logging the reminiscence handle of each variables. We are able to additionally alter the worth of x by updating the referenced worth of the pointer (we will use the * character for this) or go together with the same old make x = one thing line. We have merely logged the modified values to verify that the pointer worth replace additionally modified the worth of x. Lets say that xPointer is only a reference to x.


Now how can we obtain the identical factor in Swift? First we have now to discover ways to outline a pointer sort. This is a fast listing of all the unsafe pointer objects accessible within the Swift normal library:


You may need seen a sample right here: Unsafe|[Mutable][Raw][Buffer]Pointer[<T>].

Unsafe pointers are simply direct reminiscence addresses. All the things that’s mutable could be modified, in different phrases you may write to that handle. Uncooked signifies that there isn’t any related (generic, T) sort to the given pointer, it is only a blob of uncooked bytes. Buffers are batches (collections) of pointers.


Don’t fret if these sorts are fairly complicated for you proper now, it’s going to all make sense in a couple of minutes. Let’s get again to our unique C pattern code and port it to Swift actual fast.


var x: Int = 20
var xPointer: UnsafeMutablePointer<Int> = .init(&x)

print("x handle:", UnsafeRawPointer(&x));
print("x worth:", x);
print("pointer handle:", UnsafeRawPointer(&xPointer));
print("pointer reference:", xPointer);
print("pointer reference worth:", xPointer.pointee);


xPointer.pointee = 420;
print("x worth:", x);
print("pointer reference worth:", xPointer.pointee);

x = 69;
print("x worth:", x);
print("pointer reference worth:", xPointer.pointee);


We have created an UnsafeMutablePointer<Int> reference to our x worth, that is mainly an int* sort if we return to the C instance. We are able to use the identical ampersand (&) character to create pointers from variables. We have created a typed mutable pointer, since we might like to alter the worth of the referenced integer object (by means of the pointee property) afterward.

To print the reminiscence handle of a variable we will merely use an UnsafeRawPointer sort, as a result of we do not actually care in regards to the underlying “pointee” worth, however we simply want the handle of the reference. In the event you print a pointer sort the debug description will include the underlying reminiscence handle of the referenced object. On this case the handle of x and xPointer. 🤔



Working with typed pointers in Swift

How can we retailer some values at “unsafe” reminiscence addresses in Swift? The most straightforward manner is that we begin with a generic mutable pointer. We are able to allocate pointers utilizing the required capability, since we’re working with unsafe reminiscence, we additionally should deallocate reminiscence after we have completed utilizing it. We additionally should manually initialize pointer reference values, unsafe pointers can already include some kind of leftover information, so the protected method is to initialize them with a brand new default worth.


let numbers = [4, 8, 15, 16, 23, 42]

let pointer = UnsafeMutablePointer<Int>.allocate(capability: numbers.rely)
pointer.initialize(repeating: 0, rely: numbers.rely)
defer {
    pointer.deinitialize(rely: numbers.rely)
    pointer.deallocate()
}

for (index, worth) in numbers.enumerated() {
    pointer.superior(by: index).pointee = worth
}

print(pointer.superior(by: 5).pointee); 

let bufferPointer = UnsafeBufferPointer(begin: pointer, rely: numbers.rely) 
for (index, worth) in bufferPointer.enumerated() {
    print(index, "-", worth)
}


let bufferPointer = UnsafeMutableBufferPointer(begin: pointer, rely: numbers.rely)
for (index, _) in bufferPointer.enumerated() {
    bufferPointer[index] = index + 1
}

After we have now the allotted reminiscence storage, we will set the suitable pointee values, since we have allotted the pointer with a capability of six integer values, we will retailer as much as 6 numbers utilizing this pointer. You should use the superior(by:) methodology (pointer arithmetic (pointer + 5).pointee = 42) works as nicely) to maneuver to the following handle and set the pointee worth of it.

The very last item I might prefer to let is that you need to use a typed buffer pointer to iterate by means of these quantity references. You may consider buffer pointers as an array of pointer references. It’s doable to enumerate by means of pointer values and indexes immediately. You may replace buffer pointer values through the use of the subscript syntax on a mutable buffer pointer. 💡

We already talked in regards to the UnsafePointer, UnsafeMutablePointer, UnsafeRawPointer, UnsafeBufferPointer and UnsafeMutableBufferPointer sort let’s dive in to uncooked pointers.


Reminiscence administration utilizing uncooked pointers

Typed pointers present some form of security if it involves pointers, however how can we work with uncooked pointers? We have already seen how simple is to print out an handle of a given worth sort utilizing an UnsafeRawPointer reference, now it is time to join the dots and allocate some unsafe uncooked reminiscence. If you want to know extra about reminiscence format in Swift, please learn my earlier article.

Initially, we’ll must know the way a lot reminiscence to allocate. We are able to use the MemoryLayout struct to get information a few worth sort. We are able to use the stride and the variety of gadgets to rely how a lot byte is required to retailer our information sort utilizing a uncooked reminiscence storage.


let numbers = [4, 8, 15, 16, 23, 42]

let stride = MemoryLayout<Int>.stride
let alignment = MemoryLayout<Int>.alignment
let byteCount = stride * numbers.rely

let pointer = UnsafeMutableRawPointer.allocate(byteCount: byteCount, alignment: alignment)
defer {
    pointer.deallocate()
}
  
for (index, worth) in numbers.enumerated() {
    pointer.superior(by: stride * index).storeBytes(of: worth, as: Int.self)
}
  


let bufferPointer = UnsafeRawBufferPointer(begin: pointer, rely: byteCount)
for index in 0..&lt;numbers.rely {
    let worth = bufferPointer.load(fromByteOffset: stride * index, as: Int.self)
    print(index, "-", worth)
}

After we have allotted the required area, we will use the pointer and the superior(by:) methodology to retailer byte values of a given sort (storeBytes(of:as:)) as uncooked bytes. We are able to load a given sort utilizing the load(as:) methodology. It’s value to say that if the reminiscence doesn’t include a worth that may be represented because the given sort, incompatible worth sorts can crash your app. ☠️

Anyway, when you saved a number of values utilizing a pointer you need to use the uncooked buffer assortment to iterate by means of them and cargo again the categories as values from a given byte offset. In the event you enumerate by means of a uncooked byte buffer you too can print the byte illustration for the pointer.

If you wish to know extra about the way to Safely handle pointers in Swift, I extremely advocate watching the linked WWDC video. It is a contemporary one, the pattern code is appropriate with Swift 5. 💪





Reminiscence binding could be harmful

You should use the bindMemory and the asssumingMemoryBound strategies to transform a uncooked pointer to a typed pointer. The primary will really bind the reminiscence to a given sort, however the second perform simply returns a referenced pointer assuming it is already sure to the desired sort. You may learn extra about the important thing variations right here or examine the unique UnsafeRawPointer API proposal.


let stride = MemoryLayout<Int>.stride
let alignment = MemoryLayout<Int>.alignment
let rely = 1
let byteCount = stride * rely

let rawPointer = UnsafeMutableRawPointer.allocate(byteCount: byteCount, alignment: alignment)
defer {
    rawPointer.deallocate()
}
let pointer = rawPointer.bindMemory(to: Int.self, capability: rely)

pointer.initialize(repeating: 0, rely: rely)
defer {
    pointer.deinitialize(rely: rely)
}

pointer.pointee = 42
print(rawPointer.load(as: Int.self))
rawPointer.storeBytes(of: 69, toByteOffset: 0, as: Int.self)
print(pointer.pointee)

Binding reminiscence could be harmful, there are a few guidelines that it’s best to comply with:

  • By no means return the pointer from a withUnsafeBytes name
  • Solely bind to at least one sort at a time
  • Watch out with off-by-one errors


This text lists the problems that may occur when you re-bind a reminiscence handle.


let badPointer = rawPointer.bindMemory(to: Bool.self, capability: rely)
print(badPointer.pointee) 
 
pointer.withMemoryRebound(to: Bool.self, capability: rely) { boolPointer in
    print(boolPointer.pointee) 
}


withUnsafeBytes(of: &pointer.pointee) { pointer -> Void in
    for byte in pointer {
        print(byte)
    }
    
}


let bufferPointer = UnsafeRawBufferPointer(begin: pointer, rely: byteCount + 1)
for byte in bufferPointer {
    print(byte) 
}


I additionally advocate checking this text about reminiscence administration and byte computation in Swift. Additionally it is doable to repeat or transfer a reminiscence to a given vacation spot utilizing the assign(from:rely:) or moveAssign(from:rely:) strategies. You may learn extra about these capabilities right here.



Opaque and managed Swift pointers

If unsafe pointers weren’t simply sufficient, it’s best to know that Swift has a couple of different pointer sorts.



As Vadim Bulavin describes this in his article, with the assistance of the Unmanaged sort you may bypass Automated Reference Counting (ARC) that’s in any other case enforced to each Swift class. The opposite case is to transform objects between opaque pointers backwards and forwards.


class MyPoint {

    let x: Int
    let y: Int

    init(x: Int, y: Int) {
        self.x = x
        self.y = y
    }

    deinit {
        print("deinit", x, y)
    }
}

let unmanaged = Unmanaged.passRetained(MyPoint(x: 4, y: 20))
unmanaged.launch()

_ = Unmanaged.passUnretained(MyPoint(x: 6, y: 9))

let opaque = Unmanaged.passRetained(MyPoint(x: 1, y: 0)).toOpaque()
Unmanaged<MyPoint>.fromOpaque(opaque).launch()

Opaque pointers are used when it’s a must to work with incomplete C information constructions which can’t be represented in Swift. For instance when you have a struct that incorporates a pointer sort, that variable goes to be imported to Swift as an OpaquePointer sort when interacting with C code.

ManagedBufferPointer and the ManagedBuffer sort lets you implement your individual copy-on-write information construction. This fashion you may obtain the very same habits because the built-in array, set or dictionary sorts have. Russ Bishop has an excellent submit associated to this subject.

AutoreleasingUnsafeMutablePointer is a pointer that factors to an Goal-C reference that does not personal its goal. you may learn extra about it right here by Keith Harrison

The CVaListPointer is a straightforward wrapper round a C va_list pointer.





[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments