Swift - Difference between passing variable and passing variable address withUnsafePointer? - ios

recently I was trying to see the address of my variable and I have this question.
var age: Int = 5
withUnsafePointer(to: age) {
print($0) // 0x00007ffee3362750
print($0.pointee) // 5
}
withUnsafePointer(to: &age) {
print($0) // 0x000000010d226330
print($0.pointee) // 5
}
why it shows different memory address and why it shows the same value for the pointee?
var strarr = [1, 2]
withUnsafePointer(to: strarr[0]) {
print("\($0)") // 0x00007ffee3362750
print("\($0.pointee)") // 1
}
withUnsafePointer(to: strarr[1]) {
print("\($0)") // 0x00007ffee3362750
print("\($0.pointee)") // 2
}
withUnsafePointer(to: &strarr[0]) {
print("\($0)") // 0x0000600002755760
print("\($0.pointee)") // 1
}
withUnsafePointer(to: &strarr[1]) {
print("\($0)") // 0x0000600002755768
print("\($0.pointee)") // 2
}
for the array, why it shows the same memory address for index 1 and 2, when I'm not passing the address of the variable and why it shows a different memory address for index 1 and 2 when I'm passing the memory address?
Appreciate your answer and looking forward to understand this

The differences you see come from the fact that you are using two different overloads of withUnsafePointer, I'll list them in the same order you used them:
func withUnsafePointer<T, Result>(to value: T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
, and
func withUnsafePointer<T, Result>(to value: inout T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result
The difference between the two is the inout qualifier used for the value parameter.
Now, let's try to understand what happens behind the scenes.
First, 0x00007ffee3362750 looks like a stack pointer, while 0x000000010d226330 looks like a heap pointer. Stack addresses start at the top of the allocated memory for the program, and decrease with every function call (and increase when the function returns).
This indicates that the first overload of withUnsafePointer create a temporary writable variable from the one passed as the argument. This is needed as UnsafePointer needs an inout reference to work with, and a regular parameter is readonly.
This means that the implementation of the non-inout overload of withUnsafePointer looks something like this:
func withUnsafePointer<T, Result>(to value: T, _ body: (UnsafePointer<T>) throws -> Result) rethrows -> Result {
var value = value // shadow the argument, create a readwrite location
return try withUnsafePointer(&value, body)
}
Thus, the first call needs to allocate an intermediate memory location, and this is why you see two different addresses, it's because the addresses are not pointing to the same memory location. However, since both memory locations start with the same value, printing the pointee results in identical output.
Now, let's talk about the array example. The behaviour you see has the same cause: stack allocations. What happens is:
program starts executing, stack pointer has value P (random name)
non-inout withUnsafePointer is called, this is a function call, and stack is reserved for the function; stack pointer is P - N
withUnsafePointer creates the temporary writable variable, and executes
withUnsafePointer returns, and frees the stack memory, at this stack pointer gets back to P
second non-inout withUnsafePointer is called, the stack pointer is back to P - N, however since there were no other function calls between the two, the same stack address is reserved for the temporary writable variable, thus the UnsafePointer instance has the same address
Here, even if the UnsafePointer points to the same address, the values at that address are different, corresponding to values of arr[0] and arr[1].
As for the inout calls, the UnsafePointer point to the actual addresses of the items in the array buffer.
This is how you can get different values for the non-inout calls too:
withUnsafePointer(to: strarr[0]) {
print("\($0)")
print("\($0.pointee)")
}
// this adds a nested function call, which also decreases the stack pointer
// resulting in the temporary location not being on the same stack address
func test() {
withUnsafePointer(to: strarr[1]) {
print("\($0)")
print("\($0.pointee)")
}
}
test()

Related

How do closures capture primitive values in local scope [duplicate]

I know there are several related question and moreover I can find many posts in the Internet.
However, I can't understand the fact that closures can hold references. In case of a reference type, it is totally usual and very reasonable, but how about a value type, including struct and enum?
See this code.
let counter: () -> Int
var count = 0
do {
counter = {
count += 1
return count
}
}
count += 1 // 1
counter() // 2
counter() // 3
We can access the value type count through two ways. One is by using count directly and the another is through the closure counter.
However, if we write
let a = 0
let b = a
, in the memory b has of course a different area with a because they are value type. And this behavior is a distinct feature of value type which is different with reference type.
And then backing to the closure topic, closure has the reference to value type's variable or constant.
So, can I say the value type's feature that we can't have any references to value type is changed in case of closure's capturing values?
To me, capturing references to value type is very surprising and at the same time the experience I showed above indicates that.
Could you explain this thing?
I think the confusion is by thinking too hard about value types vs reference types. This has very little to do with that. Let's make number be reference types:
class RefInt: CustomStringConvertible {
let value: Int
init(value: Int) { self.value = value }
var description: String { return "\(value)" }
}
let counter: () -> RefInt
var count = RefInt(value: 0)
do {
counter = {
count = RefInt(value: count.value + 1)
return count
}
}
count = RefInt(value: count.value + 1) // 1
counter() // 2
counter() // 3
Does this feel different in any way? I hope not. It's the same thing, just in references. This isn't a value/reference thing.
The point is that, as you note, the closure captures the variable. Not the value of the variable, or the value of the reference the variable points to, but the variable itself). So changes to the variable inside the closure are seen in all other places that have captured that variable (including the caller). This is discussed a bit more fully in Capturing Values.
A bit deeper if you're interested (now I'm getting into a bit of technicalities that may be beyond what you care about right now):
Closures actually have a reference to the variable, and changes they make immediately occur, including calling didSet, etc. This is not the same as inout parameters, which assign the value to their original context only when they return. You can see that this way:
let counter: () -> Int
var count = 0 {
didSet { print("set count") }
}
do {
counter = {
count += 1
print("incremented count")
return count
}
}
func increaseCount(count: inout Int) {
count += 1
print("increased Count")
}
print("1")
count += 1 // 1
print("2")
counter() // 2
print("3")
counter() // 3
increaseCount(count: &count)
This prints:
1
set count
2
set count
incremented count
3
set count
incremented count
increased Count
set count
Note how "set count" is always before "incremented count" but is after "increased count." This drives home that closures really are referring to the same variable (not value or reference; variable) that they captured, and why we call it "capturing" for closures, as opposed to "passing" to functions. (You can also "pass" to closures of course, in which case they behave exactly like functions on those parameters.)

Swift memory address of outside instance of inout parameter same as copied instance

This is my playground code.
import Foundation
func printAddress<T>(anyObj: T,message: String = "") {
var copy = anyObj
withUnsafePointer(to: &copy) {
print("\(message) value \(copy) has memory address of: \($0)")
}
}
class Account {
var balance: Int = 0
init(balance: Int) {
self.balance = balance
}
}
func deposit(amount: Int, into account: inout Account) {
account.balance += amount
printAddress(anyObj: account, message: "After deposit") //0x00007fff569ba188
printAddress(anyObj: acct,message: "Address of acct within the deposit free function") //0x00007fff59eb6188
//What makes both memory addresses are same inside the fucntion?
}
func verify(account: Account) -> Bool{
printAddress(anyObj: acct,message: "Address of acct within the verify function") //0x00007fff5a39a188
//Again surprisingly same as address used in deposit function copied account var. Optimization?
return account.balance > 0
}
var acct = Account(balance: 10)
printAddress(anyObj: acct,message:"Before deposit 20") // Print 0x00007fff518751f8
deposit(amount: 20, into: &acct)
verify(account: acct)
printAddress(anyObj: acct,message:"After and deposit and verify completed") //// Print 0x00007fff518751f8
I have 2 observations that are not clear to me.
Why it prints the same memory address for account(Copied instance) and acct(The original acct)
When I print the memory address inside verify method call. Why it again same as the address used in previous method call. Is it something due to compiler optimisation.
What's happening is that you're always printing the address of the copy variable inside the printAddress() function. You're not printing the address of the argument you passed in, even though that is what you intended.
The address of the copy variable is always some constant fixed offset past the stack pointer that is current when printAddress() is entered, but the stack pointer changes depending on how deeply nested your code is when printAddress() is called.
To see yet another value, make a function foo() that calls printAddress(), and call foo() from verify().
Again, it's always the memory address of the copy variable you see at the point in time that print() is called.
If you want to print the memory address of the thing passed to printAddress(), you'll need to get rid of the temporary:
func printAddress<T>(anyObj: inout T, message: String = "") {
withUnsafePointer(to: &anyObj) {
print("\(message) value \(anyObj) has memory address of: \($0)")
}
}
Now call:
printAddress(anyObj: &acct, message: "message")
From anywhere and you'll see the same value.

Swift crashes in CFRelease when leaving scope

I've just thrown myself into iOS development and I'm current getting a runtime error in the function CFRelease just at the end of the queryServer function (I put a comment on the line that get's highlighted) and I don't have an error if I comment out the function call to extractIPFromQuery.
The code below is taking the name of a server and returning a list of ip addresses to that server.
func extractIPFromQuery(query: NSArray) -> [String] {
var addresses = [String]()
for x in 0...query.count - 1{
let adr = "\(query[x])"
let adrStart = adr.startIndex.advancedBy(10)
let adrEnd = adr.startIndex.advancedBy(18)
let address = adr.substringWithRange(Range<String.Index>(start: adrStart, end: adrEnd))
var final = ""
// Convert the hex version of the address into
// a human readable version
for seg in 0...3{
let start = address.startIndex.advancedBy(seg * 2)
let end = address.startIndex.advancedBy((seg * 2) + 2)
let hexRange = Range<String.Index>(start: start, end: end)
let hexPair = address.substringWithRange(hexRange)
final += "\(UInt8(strtoul(hexPair, nil, 16)))"
if(seg != 3){
final += "."
}
}
addresses.append(final)
}
return addresses;
}
func queryServer(hostName: String) -> [String]{
var ips = [String]()
if hostName != "\0" {
let hostRef = CFHostCreateWithName(kCFAllocatorDefault, hostName).takeRetainedValue()
while(CFHostStartInfoResolution(hostRef, CFHostInfoType.Addresses, nil) == false){}
ips += extractIPFromQuery(CFHostGetAddressing(hostRef, nil)!.takeRetainedValue() as NSArray)
} // Code breaks here
return ips
}
CFHostGetAddressing does not have "Create" or "Copy" in its name,
which means that it does not return a (+1) retained object.
Therefore you have to use takeUnretainedValue() to get the
value of the unmanaged reference.
For more information about these naming conventions, see "The Create Rule" and "The Get Rule"
in Ownership Policy
in the "Memory Management Programming Guide for Core Foundation".
You are taking ownership of the array returned by CFHostGetAddressing, which means ARC will insert a release call to balance the retain call that thinks needs to be balanced, when in fact it doesn't need to do this. You should be using takeUnretainedValue() instead of takeRetainedValue() as the name semantics of CFHostGetAddressing don't imply you are required to take ownership of the result.
At a basic level, the difference between takeRetainedValue() and takeUnretainedValue() is that the former will instruct ARC to insert a release call when the variable get's out of scope, while the latter one will not. At a semantical level, the former one tells that you want, or need to take ownership of the variable, usually meaning that there's an unbalanced retain call on that object, which ARC will balance.

How would I properly format this Swift function to map an array?

I'm trying to build a function with swift that will map an array, divide each value in the array by 3, then spit out a new array. This is what I have so far:
func divideby3Map<T, U>(y: [T], z: T -> U) -> [U] {
let array = [int]()
let divideby3Array = array.map { [y] / 3 }
return dividedby3Array
}
divideby3Map([1,2,3,4,5])
Where T and U are the original array, and the new array being returned respectively, and it's done using generics.
I'm sure this isn't written properly, I'm stuck in terms of the right syntax. For example, since the array being returned is represented by the generic [U], I assume I have to use it somewhere in the array being returned, not sure where though.
When writing a generic function, it’s sometimes easier to approach it in 3 steps: first write the code stand-alone using a specific type. Then write the code as a function, still with a specific type. Finally, change the function to be generic.
The first part, dividing an array by 3, can be done like this:
let a = [1,2,3,4,5]
// map is run on the array of integers, and returns a new
// array with the operation performed on each element in a:
let b = a.map { $0 / 3 }
// so b will be [0,0,1,1,1]
// (don’t forget, integer division truncates)
Note the closure you provide between the { } is an operation that will be applied to each element of the array. $0 represents the element, and you divide it by 3. You could also write it as a.map { i in i / 3 }.
To put this into its own function:
func divideby3Map(source: [Int]) -> [Int] {
return source.map { $0 / 3 }
}
No need to declare a fresh array – map will create one for you. You can then return that directly (you can assign it to a temporary if you prefer, but that isn’t really necessary).
Finally, if you want to make it generic, start by adding a placeholder:
func divideby3Map<T>(source: [T]) -> [T] {
return source.map { $0 / 3 }
}
Note, there’s only a need for one placeholder, T, because you are returning the exact same type you are passed in.
Except… this won’t compile, because the compiler doesn’t know that T is guaranteed to provide two critical things: the ability to divide (a / operator), and the ability to create new T from integer literals (i.e. to create a T with value 3 to divide by). Otherwise, what if we passed an array of strings or an array of arrays in?
To do this, we need to “constrain” T so our function will only accept as arguments types that provide these features. One such protocol we can use to constrain T is IntegerType, which does guarantee these features (as well as some other ones like +, * etc):
func divideby3Map<T: IntegerType>(source: [T]) -> [T] {
return source.map { $0 / 3 }
}
divideby3Map(a) // returns [0,0,1,1,1]
let smallInts: [UInt8] = [3,6,9]
divideby3Map(smallInts) // returns [1,2,3]

Why to use tuples when we can use array to return multiple values in swift

Today I was just going through some basic swift concepts and was working with some examples to understand those concepts. Right now I have completed studying tuples.
I have got one doubt i.e, what is the need of using tuples ? Ya I did some digging on this here is what I got :
We can be able to return multiple values from a function. Ok but we can also do this by returning an array.
Array ok but we can return an multiple values of different types. Ok cool but this can also be done by array of AnyObject like this :
func calculateStatistics (scores:[Int])->[AnyObject]
{
var min = scores[0]
var max = scores[0]
var sum = 0
for score in scores
{
if score > max{
max = score
}
else if score < min{
min = score
}
sum += score
}
return [min,max,"Hello"]
}
let statistics = calculateStatistics([25,39,78,66,74,80])
var min = statistics[0]
var max = statistics[1]
var msg = statistics[2] // Contains hello
We can name the objects present in the tuples. Ok but I can use a dictionary of AnyObject.
I am not saying that Why to use tuples when we have got this . But there should be something only tuple can be able to do or its easy to do it only with tuples. Moreover the people who created swift wouldn't have involved tuples in swift if there wasn't a good reason. So there should have been some good reason for them to involve it.
So guys please let me know if there's any specific cases where tuples are the best bet.
Thanks in advance.
Tuples are anonymous structs that can be used in many ways, and one of them is to make returning multiple values from a function much easier.
The advantages of using a tuple instead of an array are:
multiple types can be stored in a tuple, whereas in an array you are restricted to one type only (unless you use [AnyObject])
fixed number of values: you cannot pass less or more parameters than expected, whereas in an array you can put any number of arguments
strongly typed: if parameters of different types are passed in the wrong positions, the compiler will detect that, whereas using an array that won't happen
refactoring: if the number of parameters, or their type, change, the compiler will produce a relevant compilation error, whereas with arrays that will pass unnoticed
named: it's possible to associate a name with each parameter
assignment is easier and more flexible - for example, the return value can be assigned to a tuple:
let tuple = functionReturningTuple()
or all parameters can be automatically extracted and assigned to variables
let (param1, param2, param3) = functionReturningTuple()
and it's possible to ignore some values
let (param1, _, _) = functionReturningTuple()
similarity with function parameters: when a function is called, the parameters you pass are actually a tuple. Example:
// SWIFT 2
func doSomething(number: Int, text: String) {
println("\(number): \(text)")
}
doSomething(1, "one")
// SWIFT 3
func doSomething(number: Int, text: String) {
print("\(number): \(text)")
}
doSomething(number: 1, text: "one")
(Deprecated in Swift 2) The function can also be invoked as:
let params = (1, "one")
doSomething(params)
This list is probably not exhaustive, but I think there's enough to make you favor tuples to arrays for returning multiple values
For example, consider this simple example:
enum MyType {
case A, B, C
}
func foo() -> (MyType, Int, String) {
// ...
return (.B, 42, "bar")
}
let (type, amount, desc) = foo()
Using Array, to get the same result, you have to do this:
func foo() -> [Any] {
// ...
return [MyType.B, 42, "bar"]
}
let result = foo()
let type = result[0] as MyType, amount = result[1] as Int, desc = result[2] as String
Tuple is much simpler and safer, isn't it?
Tuple is a datastructure which is lighter weight than heterogeneous Array. Though they're very similar, in accessing the elements by index, the advantage is tuples can be constructed very easily in Swift. And the intention to introduce/interpolate this(Tuple) data structure is Multiple return types. Returning multiple data from the 'callee' with minimal effort, that's the advantage of having Tuples. Hope this helps!
A tuple is ideally used to return multiple named data from a function for temporary use. If the scope of the tuple is persistent across a program you might want to model that data structure as a class or struct.

Resources