swift616
swift616

Reputation: 58

UnsafePointer<Int8> not working

The following unit test always fails as some UnsafePointer equal some other. This behavior I observe for at least 3 strings. I'm using Xcode Version 9.1 (9B55) on High Sierra Version 10.13.1 (17B48).

func testUnsafePointer() {
    let a = "aaa"
    let b = "bbb"
    let c = "ccc"

    let ua = UnsafePointer<Int8>(a)
    let ub = UnsafePointer<Int8>(b)
    let uc = UnsafePointer<Int8>(c)

    print("a: '\(a)', ua: '\(ua)'")
    print("b: '\(b)', ub: '\(ub)'")
    print("c: '\(c)', uc: '\(uc)'")

    XCTAssertTrue(ua != ub)
    XCTAssertTrue(ub != uc)
    XCTAssertTrue(uc != ua)
}

The printout looks similar to this

a: 'aaa', ua: '0x000060c000056a30'
b: 'bbb', ub: '0x00006080000530d0'
c: 'ccc', uc: '0x00006080000530d0'

NB. in the swift playground everything looks ok.

Upvotes: 2

Views: 826

Answers (1)

Martin R
Martin R

Reputation: 539755

In

let ua = UnsafePointer<Int8>(a)

the

init(_ other: UnsafePointer<Pointee>)

initializer of UnsafePointer is called. I.e. you are passing a Swift String to a function taking a UnsafePointer<Int8> argument. In that case a temporary C string representation is created and passed to the function, compare String value to UnsafePointer<UInt8> function parameter behavior.

That temporary C string is only valid for the duration of the function call, and on return, it is not guaranteed that the memory pointed to by ua still contains that C string (or any valid data). In addition,

let ua = UnsafePointer<Int8>(a)
let ub = UnsafePointer<Int8>(b)
let uc = UnsafePointer<Int8>(c)

can use the same storage for the temporary C string, in that case the pointers would be equal, as you observed.


If your intention is to call a C function taking const char * arguments, then you can simply pass the Swift strings. The compiler will insert the necessary code to create C string representations (which are again valid for the duration of the function call), as explained in String value to UnsafePointer<UInt8> function parameter behavior:

let a = "aaa"
let b = "bbb"
let c = "ccc"

cfunc(a, b, c)

Upvotes: 2

Related Questions