Printing a variable memory address in swift

前端 未结 15 1019
天涯浪人
天涯浪人 2020-11-28 01:16

Is there anyway to simulate the [NSString stringWithFormat:@\"%p\", myVar], from Objective-C, in the new Swift language?

For example:

le         


        
相关标签:
15条回答
  • 2020-11-28 01:31

    To get the (heap) address of an object

    func address<T: AnyObject>(o: T) -> Int {
        return unsafeBitCast(o, Int.self)
    }
    
    class Test {}
    var o = Test()
    println(NSString(format: "%p", address(o))) // -> 0x7fd5c8700970
    

    (Edit: Swift 1.2 now includes a similar function called unsafeAddressOf.)

    In Objective-C this would be [NSString stringWithFormat:@"%p", o].

    o is a reference to the instance. So if o is assigned to another variable o2, the returned address for o2 will be the same.

    This doesn't apply to structs (including String) and primitive types (like Int), because those live directly on the stack. But we can retrieve the location on the stack.

    To get the (stack) address of a struct, build-in type or object reference

    func address(o: UnsafePointer<Void>) -> Int {
        return unsafeBitCast(o, Int.self)
    }
    
    println(NSString(format: "%p", address(&o))) // -> 0x10de02ce0
    
    var s = "A String"
    println(NSString(format: "%p", address(&s))) // -> 0x10de02ce8
    
    var i = 55
    println(NSString(format: "%p", address(&i))) // -> 0x10de02d00
    

    In Objective-C this would be [NSString stringWithFormat:@"%p", &o] or [NSString stringWithFormat:@"%p", &i].

    s is struct. So if s is assigned to another variable s2, the value will be copied and the returned address for s2 will be different.

    How it fits together (pointer recap)

    Like in Objective-C, there are two different addresses associated with o. The first is the location of the object, the second is the location of the reference (or pointer) to the object.

    Yes, this means that the content of address 0x7fff5fbfe658 is the number 0x6100000011d0 as the debugger can tell us:

    (lldb) x/g 0x7fff5fbfe658
    0x7fff5fbfe658: 0x00006100000011d0
    

    So, except for strings being structs, internally this all pretty much works the same as in (Objective-)C.

    (Current as of Xcode 6.3)

    0 讨论(0)
  • 2020-11-28 01:32

    The other answers are fine, though I was looking for a way to get the pointer address as an integer:

    let ptr = unsafeAddressOf(obj)
    let nullPtr = UnsafePointer<Void>(bitPattern: 0)
    
    /// This gets the address of pointer
    let address = nullPtr.distanceTo(ptr) // This is Int
    

    Just a little follow-up.

    0 讨论(0)
  • 2020-11-28 01:33

    This is certainly not the fastest or safest way to go about it. But it works for me. This will allow for any nsobject subclass to adopt this property.

    public extension NSObject {
        public var memoryAddress : String? {
            let str = "\(self.self)".components(separatedBy: ": ")
            guard str.count > 1 else { return nil }
            return str[1].replacingOccurrences(of: ">", with: "")            
        }
    }
    
    //usage 
    let foo : String! = "hello"
    Swift.print(foo.memoryAddress) // prints 0x100f12980
    
    0 讨论(0)
  • 2020-11-28 01:34

    If you just want to see this in the debugger and not do anything else with it, there's no need to actually get the Int pointer. To get the string representation of an object's address in memory, just use something like this:

    public extension NSObject { // Extension syntax is cleaner for my use. If your needs stem outside NSObject, you may change the extension's target or place the logic in a global function
        public var pointerString: String {
            return String(format: "%p", self)
        }
    }
    

    Example usage:

    print(self.pointerString, "Doing something...")
    // Prints like: 0x7fd190d0f270 Doing something...
    

    Additionally, remember that you can simply print an object without overriding its description, and it will show its pointer address alongside more descriptive (if oft cryptic) text.

    print(self, "Doing something else...")
    // Prints like: <MyModule.MyClass: 0x7fd190d0f270> Doing something else...
    // Sometimes like: <_TtCC14__lldb_expr_668MyModule7MyClass: 0x7fd190d0f270> Doing something else...
    
    0 讨论(0)
  • 2020-11-28 01:37

    The answer @Drew provide can only be used for class type.
    The answer @nschum provide can only be for struct type.

    However if you use the second method to get address of a array with value type element. Swift will copy the whole array because in Swift array is copy-on-write and Swift can't make sure it behave this way once it pass control over to C/C++ (Which is trigger by using & to get address). And if you use first method instead , it will automatically convert Array to NSArray which is surely something we don't want.

    So the most simple and unified way I found is using lldb instruction frame variable -L yourVariableName.

    Or you can combine their answers:

    func address(o: UnsafePointer<Void>) {
        let addr = unsafeBitCast(o, Int.self)
        print(NSString(format: "%p", addr))
    }
    
    func address<T: AnyObject>(o: T) -> String{
        let addr = unsafeBitCast(o, Int.self)
        return NSString(format: "%p", addr) as String
    }
    
    0 讨论(0)
  • 2020-11-28 01:43

    Swift 2

    This is now part of the standard library: unsafeAddressOf.

    /// Return an UnsafePointer to the storage used for `object`.  There's
    /// not much you can do with this other than use it to identify the
    /// object
    

    Swift 3

    For Swift 3, use withUnsafePointer:

    var str = "A String"
    withUnsafePointer(to: &str) {
        print(" str value \(str) has address: \($0)")
    }
    
    0 讨论(0)
提交回复
热议问题