在swift中打印可变内存地址

 骁炉 发布于 2023-01-11 15:04

无论如何都要[NSString stringWithFormat:@"%p", myVar]用新的快速语言模拟代码?

例如:

let str = "A String"
println(" str value \(str) has address: ?")

Woodstock.. 160

Swift 4.X:

print(Unmanaged.passUnretained(someVar).toOpaque())

打印someVar的内存地址.(感谢@Ying)


Swift 3.1:
print(Unmanaged.passUnretained(someVar as AnyObject).toOpaque())

打印someVar的内存地址.


Xcode 8.2.1自动更正告诉我现在是`print(Unmanaged <AnyObject> .passUnretained(someVar as AnyObject).toOpaque())` (2认同)

@OutOnAWeekend你是对的,很可能是因为结构在作为参数传递时被复制了.使用`Unmanaged`它可以这样做:`print(Unmanaged .fromOpaque(&myStruct).toOpaque())`. (2认同)


Drew.. 104

斯威夫特2

这是标准库的一部分: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
斯威夫特3

对于Swift 3,请使用withUnsafePointer:

var str = "A String"
withUnsafePointer(to: &str) {
    print(" str value \(str) has address: \($0)")
}

如果我想用Swift 3打印**immutable**值的地址怎么办?`withUnsafePointer`导致`无法将不可变值作为inout argument`错误传递. (28认同)

即使它被接受并且得到最高投票答案,它仍然会给出错误的**结果.示例:`print(self.description)`打印``,我们将其用作参考.`var mutableSelf = self; withUnsafePointer(to:&mutableSelf){print(String(format:"%p",$ 0))}`打印`0x16fde4028`,这是明显不同的地址.谁能解释为什么? (12认同)

@nyg你的回答给了我一个实际错误原因的线索:`UnsafePointer`是一个结构,所以为了打印_指向它的地址_(而不是结构本身)你必须打印`String(格式:"%p ",$ 0.pointee)`! (7认同)

顺便说一句,这按预期打印`0x101c1d580`:`print(String(format:"%p",unsafeBitCast(self,to:Int.self))) (4认同)

unsafeAddressOf()仅适用于类类型(如下面的@Nick所述).因此,只有在导入Foundation并将String桥接到NSString时,此答案才有效.在普通的Swift中,String是一个值类型,unsafeAddressOf不能用于获取其地址(尝试导致编译错误). (2认同)


LombaX.. 50

请注意,这个答案很老了.它描述的许多方法不再有效.具体.core不能再访问了.

然而,@ drew的回答是正确而简单的:

现在这是标准库的一部分:unsafeAddressOf.

所以你的问题的答案是:

println(" str value \(str) has address: \(unsafeAddressOf(str))")

以下是标记正确的原始答案(后代/礼貌):

斯威夫特"隐藏"指针,但它们仍然存在于引擎盖下.(因为运行时需要它,并且出于与Objc和C的兼容性原因)

但是要知道的事情很少,但首先如何打印Swift String的内存地址?

    var aString : String = "THIS IS A STRING"
    NSLog("%p", aString.core._baseAddress)  // _baseAddress is a COpaquePointer
   // example printed address 0x100006db0

这将打印字符串的内存地址,如果打开XCode - > Debug Workflow - > View Memory并转到打印地址,您将看到该字符串的原始数据.由于这是一个字符串文字,因此这是二进制文件存储区内的内存地址(不是堆栈或堆).

但是,如果你这样做

    var aString : String = "THIS IS A STRING" + "This is another String"
    NSLog("%p", aString.core._baseAddress)

    // example printed address 0x103f30020

这将在堆栈上,因为字符串是在运行时创建的

注意:.core._baseAddress没有记录,我发现它在变量检查器中查找,它可能在将来隐藏

_baseAddress并非适用于所有类型,此处是CInt的另一个示例

    var testNumber : CInt = 289
    takesInt(&testNumber)

这样takesInt的C辅助函数在哪里

void takesInt(int *intptr)
{
    printf("%p", intptr);
}

在Swift方面,这个函数是takesInt(intptr: CMutablePointer),所以它需要CMutablePointer到CInt,你可以使用&varname获取它

该函数打印0x7fff5fbfed98,在此内存地址,您将找到289(十六进制表示法).您可以使用更改其内容*intptr = 123456

现在,还有其他一些事要知道.

swift中的字符串是原始类型,而不是对象.
CInt是映射到C int Type的Swift类型.
如果你想要一个对象的内存地址,你必须做一些不同的事情.
Swift有一些可以在与C交互时使用的指针类型
,你可以在这里阅读它们:Swift指针类型此外,你可以更多地了解它们探索它们的声明(cmd +点击类型),以了解如何转换一种指向另一种的指针

    var aString : NSString = "This is a string"  // create an NSString
    var anUnmanaged = Unmanaged.passUnretained(aString)   // take an unmanaged pointer
    var opaque : COpaquePointer = anUnmanaged.toOpaque()   // convert it to a COpaquePointer
    var mut : CMutablePointer = &opaque   // this is a CMutablePointer

    printptr(mut)   // pass the pointer to an helper function written in C

printptr 是我用这个实现创建的C辅助函数

void printptr(void ** ptr)
{
    printf("%p", *ptr);
}

再次,打印地址的示例:0x6000000530b0,如果您通过内存检查器,您将找到您的NSString

你可以用Swift中的指针做一件事(这甚至可以使用inout参数完成)

    func playWithPointer (stringa :AutoreleasingUnsafePointer) 
    {
        stringa.memory = "String Updated";
    }

    var testString : NSString = "test string"
    println(testString)
    playWithPointer(&testString)
    println(testString)

或者,与Objc/c交互

// objc side
+ (void)writeString:(void **)var
{
    NSMutableString *aString = [[NSMutableString alloc] initWithFormat:@"pippo %@", @"pluto"];
    *var = (void *)CFBridgingRetain(aString);   // Retain!
}

// swift side
var opaque = COpaquePointer.null()   // create a new opaque pointer pointing to null
TestClass.writeString(&opaque)
var string = Unmanaged.fromOpaque(opaque).takeRetainedValue()
println(string)
// this prints pippo pluto


nschum.. 19

获取对象的(堆)地址

func address(o: T) -> Int {
    return unsafeBitCast(o, Int.self)
}

class Test {}
var o = Test()
println(NSString(format: "%p", address(o))) // -> 0x7fd5c8700970

(编辑: Swift 1.2现在包含一个类似的函数unsafeAddressOf.)

在Objective-C中,这将是[NSString stringWithFormat:@"%p", o].

o是对实例的引用.因此,如果o分配给另一个变量o2,则返回的地址o2将是相同的.

这不适用于结构(包括String)和原始类型(如Int),因为它们直接存在于堆栈中.但我们可以检索堆栈上的位置.

获取结构的(堆栈)地址,内置类型或对象引用

func address(o: UnsafePointer) -> 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

在Objective-C中,这将是[NSString stringWithFormat:@"%p", &o][NSString stringWithFormat:@"%p", &i].

s是结构.因此,如果s分配给另一个变量s2,则将复制该值,并且返回的地址s2将不同.

它是如何组合在一起的(指针回顾)

与Objective-C类似,有两个不同的地址相关联o.第一个是对象的位置,第二个是对象的引用(或指针)的位置.

是的,这意味着地址0x7fff5fbfe658的内容是数字0x6100000011d0,因为调试器可以告诉我们:

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

因此,除了字符串是结构体之外,这在内部这几乎与(Objective-)C中的相同.

(截至Xcode 6.3的当前版本)

10 个回答
  • 如果你只是想在调试器中看到这个而不用它做任何其他事情,那么就没有必要实际获得Int指针.要在内存中获取对象地址的字符串表示,只需使用以下内容:

    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)
        }
    }
    

    用法示例:

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

    另外,请记住,您可以简单地打印一个对象而不会覆盖它description,并且它将显示其指针地址以及更具描述性(如果经常是神秘的)文本.

    print(self, "Doing something else...")
    // Prints like: <MyModule.MyClass: 0x7fd190d0f270> Doing something else...
    // Sometimes like: <_TtCC14__lldb_expr_668MyModule7MyClass: 0x7fd190d0f270> Doing something else...
    

    2023-01-11 15:05 回答
  • 只要用这个:

    print(String(format: "%p", object))
    

    2023-01-11 15:05 回答
  • 斯威夫特2

    这是标准库的一部分: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
    

    斯威夫特3

    对于Swift 3,请使用withUnsafePointer:

    var str = "A String"
    withUnsafePointer(to: &str) {
        print(" str value \(str) has address: \($0)")
    }
    

    2023-01-11 15:05 回答
  • 获取对象的(堆)地址

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

    (编辑: Swift 1.2现在包含一个类似的函数unsafeAddressOf.)

    在Objective-C中,这将是[NSString stringWithFormat:@"%p", o].

    o是对实例的引用.因此,如果o分配给另一个变量o2,则返回的地址o2将是相同的.

    这不适用于结构(包括String)和原始类型(如Int),因为它们直接存在于堆栈中.但我们可以检索堆栈上的位置.

    获取结构的(堆栈)地址,内置类型或对象引用

    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
    

    在Objective-C中,这将是[NSString stringWithFormat:@"%p", &o][NSString stringWithFormat:@"%p", &i].

    s是结构.因此,如果s分配给另一个变量s2,则将复制该值,并且返回的地址s2将不同.

    它是如何组合在一起的(指针回顾)

    与Objective-C类似,有两个不同的地址相关联o.第一个是对象的位置,第二个是对象的引用(或指针)的位置.

    是的,这意味着地址0x7fff5fbfe658的内容是数字0x6100000011d0,因为调试器可以告诉我们:

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

    因此,除了字符串是结构体之外,这在内部这几乎与(Objective-)C中的相同.

    (截至Xcode 6.3的当前版本)

    2023-01-11 15:05 回答
  • TL; DR

    struct MemoryAddress<T>: CustomStringConvertible {
    
        let intValue: Int
    
        var description: String {
            let length = 2 + 2 * MemoryLayout<UnsafeRawPointer>.size
            return String(format: "%0\(length)p", intValue)
        }
    
        // for structures
        init(of structPointer: UnsafePointer<T>) {
            intValue = Int(bitPattern: structPointer)
        }
    }
    
    extension MemoryAddress where T: AnyObject {
    
        // for classes
        init(of classInstance: T) {
            intValue = unsafeBitCast(classInstance, to: Int.self)
            // or      Int(bitPattern: Unmanaged<T>.passUnretained(classInstance).toOpaque())
        }
    }
    
    /* Testing */
    
    class MyClass { let foo = 42 }
    var classInstance = MyClass()
    let classInstanceAddress = MemoryAddress(of: classInstance) // and not &classInstance
    print(String(format: "%018p", classInstanceAddress.intValue))
    print(classInstanceAddress)
    
    struct MyStruct { let foo = 1 } // using empty struct gives weird results (see comments)
    var structInstance = MyStruct()
    let structInstanceAddress = MemoryAddress(of: &structInstance)
    print(String(format: "%018p", structInstanceAddress.intValue))
    print(structInstanceAddress)
    
    /* output
    0x0000000101009b40
    0x0000000101009b40
    0x00000001005e3000
    0x00000001005e3000
    */
    

    (要点)


    在Swift中,我们处理值类型(结构)或引用类型(类).做的时候:

    let n = 42 // Int is a structure, i.e. value type
    

    一些内存在地址X分配,在这个地址我们将找到值42. Doing &n创建一个指向地址X的指针,因此&n告诉我们在哪里n.

    (lldb) frame variable -L n
    0x00000001005e2e08: (Int) n = 42
    (lldb) memory read -c 8 0x00000001005e2e08
    0x1005e2e08: 2a 00 00 00 00 00 00 00 // 0x2a is 42
    

    做的时候:

    class C { var foo = 42, bar = 84 }
    var c = C()
    

    内存分配在两个地方:

    在类实例数据所在的地址Y处

    在类实例引用所在的地址X处.

    如上所述,类是引用类型:因此值c位于地址X,在此处我们将找到Y的值.在地址Y + 16处,我们将找到foo并且在地址Y + 24处我们将找到bar(在+ 0和+ 8我们会找到类型数据和引用计数,我不能告诉你更多关于这个......).

    (lldb) frame variable c // gives us address Y
    (testmem.C) c = 0x0000000101a08f90 (foo = 42, bar = 84)
    (lldb) memory read 0x0000000101a08f90 // reading memory at address Y
    0x101a08f90: e0 65 5b 00 01 00 00 00 02 00 00 00 00 00 00 00
    0x101a08fa0: 2a 00 00 00 00 00 00 00 54 00 00 00 00 00 00 00
    

    0x2a是42(foo)并且0x54是84(bar).

    在这两种情况下,使用&n&c将给我们地址X.对于值类型,这是我们想要的,但不是参考类型.

    做的时候:

    let referencePointer = UnsafeMutablePointer<C>(&c)
    

    我们在引用上创建一个指针,即指向地址X的指针.使用时也一样withUnsafePointer(&c) {}.

    (lldb) frame variable referencePointer
    (UnsafeMutablePointer<testmem.C>) referencePointer = 0x00000001005e2e00 // address X
    (lldb) memory read -c 8 0x00000001005e2e00 // read memory at address X
    0x1005e2e00: 20 ec 92 01 01 00 00 00 // contains address Y, consistent with result below:
    (lldb) frame variable c
    (testmem.C) c = 0x000000010192ec20 (foo = 42, bar = 84)
    

    现在我们已经更好地理解了底层的内容,现在我们在地址X处找到地址Y(我们想要的地址),我们可以执行以下操作来获取它:

    let addressY = unsafeBitCast(c, to: Int.self)
    

    验证:

    (lldb) frame variable addressY -f hex
    (Int) addressY = 0x0000000101b2fd20
    (lldb) frame variable c
    (testmem.C) c = 0x0000000101b2fd20 (foo = 42, bar = 84)
    

    还有其他方法可以做到这一点:

    let addressY1 = Int(bitPattern: Unmanaged.passUnretained(c).toOpaque())
    let addressY2 = withUnsafeMutableBytes(of: &c) { $0.load(as: Int.self) }
    

    toOpaque()实际上叫unsafeBitCast(c, to: UnsafeMutableRawPointer.self).

    我希望这有帮助......它对我有用.

    2023-01-11 15:06 回答
  • Swift 4.X:

    print(Unmanaged.passUnretained(someVar).toOpaque())
    

    打印someVar的内存地址.(感谢@Ying)


    Swift 3.1:

    print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
    

    打印someVar的内存地址.


    2023-01-11 15:06 回答
  • 参考类型:

    获取引用类型的内存地址是有意义的,因为它代表了身份.

    === identity运算符用于检查2个对象是否指向相同的引用.

    使用ObjectIdentifier得到的内存地址

    码:

    class C {}
    
    let c1 = C()
    let c2 = c1
    
    //Option 1:
    print("c1 address: \(Unmanaged.passUnretained(c1).toOpaque())") 
    
    //Option 2:
    let o1 = ObjectIdentifier(c1)
    let o2 = ObjectIdentifier(c2)
    
    print("o1 -> c1 = \(o1)")
    print("o2 -> c2 = \(o2)")
    
    if o1 == o2 {
        print("c1 = c2")
    } else {
        print("c1 != c2")
    }
    
    //Output:
    //c1 address: 0x000060c000005b10
    //o1 -> c1 = ObjectIdentifier(0x000060c000005b10)
    //o2 -> c2 = ObjectIdentifier(0x000060c000005b10)
    //c1 = c2
    

    价值类型:

    获取值类型的内存地址的需要没有多大意义(因为它是一个值),并且重点将更多地放在值的相等性上.

    2023-01-11 15:06 回答
  • 斯威夫特4

    extension String {
        static func pointer(_ object: AnyObject?) -> String {
            guard let object = object else { return "nil" }
            let opaque: UnsafeMutableRawPointer = Unmanaged.passUnretained(object).toOpaque()
            return String(describing: opaque)
        }
    }
    

    用法:

    print("FileManager.default: \(String.pointer(FileManager.default))")
    // FileManager.default: 0x00007fff5c287698
    
    print("nil: \(String.pointer(nil))")
    // nil: nil
    

    2023-01-11 15:06 回答
  • 请注意,这个答案很老了.它描述的许多方法不再有效.具体.core不能再访问了.

    然而,@ drew的回答是正确而简单的:

    现在这是标准库的一部分:unsafeAddressOf.

    所以你的问题的答案是:

    println(" str value \(str) has address: \(unsafeAddressOf(str))")
    

    以下是标记正确的原始答案(后代/礼貌):

    斯威夫特"隐藏"指针,但它们仍然存在于引擎盖下.(因为运行时需要它,并且出于与Objc和C的兼容性原因)

    但是要知道的事情很少,但首先如何打印Swift String的内存地址?

        var aString : String = "THIS IS A STRING"
        NSLog("%p", aString.core._baseAddress)  // _baseAddress is a COpaquePointer
       // example printed address 0x100006db0
    

    这将打印字符串的内存地址,如果打开XCode - > Debug Workflow - > View Memory并转到打印地址,您将看到该字符串的原始数据.由于这是一个字符串文字,因此这是二进制文件存储区内的内存地址(不是堆栈或堆).

    但是,如果你这样做

        var aString : String = "THIS IS A STRING" + "This is another String"
        NSLog("%p", aString.core._baseAddress)
    
        // example printed address 0x103f30020
    

    这将在堆栈上,因为字符串是在运行时创建的

    注意:.core._baseAddress没有记录,我发现它在变量检查器中查找,它可能在将来隐藏

    _baseAddress并非适用于所有类型,此处是CInt的另一个示例

        var testNumber : CInt = 289
        takesInt(&testNumber)
    

    这样takesInt的C辅助函数在哪里

    void takesInt(int *intptr)
    {
        printf("%p", intptr);
    }
    

    在Swift方面,这个函数是takesInt(intptr: CMutablePointer<CInt>),所以它需要CMutablePointer到CInt,你可以使用&varname获取它

    该函数打印0x7fff5fbfed98,在此内存地址,您将找到289(十六进制表示法).您可以使用更改其内容*intptr = 123456

    现在,还有其他一些事要知道.

    swift中的字符串是原始类型,而不是对象.
    CInt是映射到C int Type的Swift类型.
    如果你想要一个对象的内存地址,你必须做一些不同的事情.
    Swift有一些可以在与C交互时使用的指针类型
    ,你可以在这里阅读它们:Swift指针类型此外,你可以更多地了解它们探索它们的声明(cmd +点击类型),以了解如何转换一种指向另一种的指针

        var aString : NSString = "This is a string"  // create an NSString
        var anUnmanaged = Unmanaged<NSString>.passUnretained(aString)   // take an unmanaged pointer
        var opaque : COpaquePointer = anUnmanaged.toOpaque()   // convert it to a COpaquePointer
        var mut : CMutablePointer = &opaque   // this is a CMutablePointer<COpaquePointer>
    
        printptr(mut)   // pass the pointer to an helper function written in C
    

    printptr 是我用这个实现创建的C辅助函数

    void printptr(void ** ptr)
    {
        printf("%p", *ptr);
    }
    

    再次,打印地址的示例:0x6000000530b0,如果您通过内存检查器,您将找到您的NSString

    你可以用Swift中的指针做一件事(这甚至可以使用inout参数完成)

        func playWithPointer (stringa :AutoreleasingUnsafePointer<NSString>) 
        {
            stringa.memory = "String Updated";
        }
    
        var testString : NSString = "test string"
        println(testString)
        playWithPointer(&testString)
        println(testString)
    

    或者,与Objc/c交互

    // objc side
    + (void)writeString:(void **)var
    {
        NSMutableString *aString = [[NSMutableString alloc] initWithFormat:@"pippo %@", @"pluto"];
        *var = (void *)CFBridgingRetain(aString);   // Retain!
    }
    
    // swift side
    var opaque = COpaquePointer.null()   // create a new opaque pointer pointing to null
    TestClass.writeString(&opaque)
    var string = Unmanaged<NSString>.fromOpaque(opaque).takeRetainedValue()
    println(string)
    // this prints pippo pluto
    

    2023-01-11 15:06 回答
  • 在关于数组的Swift4中:

        let array1 = [1,2,3]
        let array2 = array1
        array1.withUnsafeBufferPointer { (point) in
            print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
        }
        array2.withUnsafeBufferPointer { (point) in
            print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
        }
    

    2023-01-11 15:09 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有