신속한 메모리 주소 인쇄


165

어쨌든 [NSString stringWithFormat:@"%p", myVar]Objective-C에서 새로운 Swift 언어로 를 시뮬레이션 할 수 있습니까?

예를 들면 다음과 같습니다.

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

2
에서 [NSString stringWithFormat:@"%p", myVar], myVar포인터이어야합니다. Swift 코드에서 str포인터가 아닙니다. 따라서 비교는 적용되지 않습니다.
user102008

5
적어도 이것을 입력 할 때 위의 두 주석이 잘못되었음을 주목할 가치가 있습니다.
Ben Leggiero

답변:


112

스위프트 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

스위프트 3의 경우 다음을 사용하십시오 withUnsafePointer.

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

2
unsafeAddressOf ()는 클래스 유형에 대해서만 작동합니다 (@Nick은 아래 참조). 따라서이 답변은 Foundation을 가져오고 문자열이 NSString에 브리지 된 경우에만 작동합니다. 일반 Swift에서 String은 값 유형이며 unsafeAddressOf를 사용하여 주소를 사용할 수 없습니다 (시도 결과 컴파일 오류가 발생 함).
Stephen Schaub

29
Swift 3 으로 불변 값의 주소를 인쇄하려면 어떻게합니까? withUnsafePointer결과 cannot pass immutable value as inout argument오류가 발생했습니다.
Alexander Vasenin

12
받아 들여지고 가장 많이 투표 된 답변이지만 여전히 잘못된 결과를 제공 합니다. 예 : print(self.description)prints <MyViewController: 0x101c1d580>, 우리는 그것을 참조로 사용합니다. 주소가 다른 var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }인쇄물 0x16fde4028. 아무도 이유를 설명 할 수 있습니까?
Alexander Vasenin

4
BTW,이 인쇄는 0x101c1d580예상대로 :print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
알렉산더 Vasenin

8
@nyg 당신의 대답은 실제 오류 원인에 대한 단서를주었습니다 : UnsafePointer구조체입니다. 그래서 주소 를 인쇄 하려면 (구조 자체가 아닌) 주소 를 인쇄하려면 인쇄해야합니다 String(format: "%p", $0.pointee)!
Alexander Vasenin

213

참고 : 이것은 참조 유형입니다.

스위프트 4/5 :

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

someVar의 메모리 주소를 인쇄합니다. (@Ying 덕분에)


스위프트 3.1 :

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

someVar의 메모리 주소를 인쇄합니다.



2
Xcode 8.2.1 자동 print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Jeff

2
someVar가 객체 인 경우에만 그렇지 않습니다. someVar가 구조체와 같은 값 유형 인 경우 실행될 때마다 다른 주소를 제공합니다.
OutOnAWeekend

3
@OutOnAWeekend 당신이 맞습니다. 아마도 인수로 전달 될 때 구조가 복사되기 때문일 것입니다. 다음 Unmanaged과 같이 사용할 수 있습니다 print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque()).
nyg

1
스위프트 4 현재, 나는이 주문을 인쇄 할 수있었습니다- Unmanaged.passUnretained(someVar).toOpaque()(일반 사양 필요 없음)
Ying

2
스위프트 4 답변은 완벽합니다. 인쇄하지 않고 문자열 표현을 얻으려면 debugDescription끝에 추가 하는 것이 좋습니다 .
Patrick

51

이 답변은 상당히 오래되었습니다. 설명하는 많은 방법이 더 이상 작동하지 않습니다. 특히 .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-> 디버그 워크 플로-> 메모리보기를 열고 인쇄 된 주소로 이동하면 문자열의 원시 데이터가 표시됩니다. 이것은 문자열 리터럴이므로 이진 저장소 (스택 또는 힙이 아님) 내의 메모리 주소입니다.

그러나 당신이 할 경우

    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 (16 진수 표기) 찾을 수 있습니다. 당신은 그것으로 내용을 변경할 수 있습니다*intptr = 123456

이제 알아야 할 다른 것들이 있습니다.

즉, 문자열은 객체가 아닌 기본 유형입니다.
CInt는 C int 유형에 매핑 된 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에서 포인터로 할 수있는 한 가지 작업 (입력 매개 변수로 수행 할 수도 있음)

    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

그렇습니다. 포인터는 나가야 만하지만 호환성 문제 때문에 참조해야합니다. 운영 체제에서 일반적으로 사용되는 포인터 언어가 고급 언어 인 경우에도 운영 체제 엔진에서 언제든지 모든 언어로 포인터가 존재해야합니다.
holex

나는 "호환성 이유와 런타임이 필요하기 때문에"라고 :-) 두 번째 문은 당신이 말하는 요약이 표시 (나는 몇 마디를 소비하므로, 프로그래머가 알고 있다고 가정하고 그것을 이해)
LombaX

더 이상 적용되지 않는다고 가정합니까?
aleclarson

예. @Drew의 정답을 편집했습니다.
Rog

@LombaX 참조 유형의 주소 만 인쇄 할 수 있습니까? 변수의 주소를 인쇄 할 수 없습니까?
AbhimanyuAryan

21

객체의 (힙) 주소를 얻으려면

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 현재)


흠. 객체 속성의 스택 주소를 얻는 것이 일관되지 않습니다. 어떤 아이디어? 이 요점을 확인하십시오!
aleclarson

객체의 속성은 스택이 아니라 힙에 있습니다. 클래스 인스턴스의 속성을 UnsafePointer로 전달하면 Swift가 실제로 값을 먼저 복사하고 사본의 주소를 얻습니다. C 코드가 객체의 인터페이스를 우회하여 일관성이없는 상태를 일으키는 것을 막는 것 같습니다. 그 주위에 방법이 있는지 모르겠습니다.
nschum

여기 Apple Developer Forums에서 만든 스레드가 있습니다. 거기에 좋은 답변이 있습니다.
aleclarson

20

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를 찾을 수 있습니다. 그렇게하면 &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

0x2a42 (foo)이고 0x5484 (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).

나는 이것이 도움이 되었기를 바란다.


방금 2 개의 다른 인스턴스를 통해 동일한 구조체의 주소를 인쇄하려고 MemoryLocation하면 2 개의 다른 주소 가 생성됩니다.
user1046037

@ user1046037 감사합니다. 클래스 init를 변경했습니다. 또한 빈 구조체를 사용하는 경우에만 두 개의 다른 주소를 얻습니다. 빈 구조체를 사용하면 항상 이상한 결과가 나옵니다. 내 생각 엔 컴파일러가 최적화를하는 것 같다.
nyg

@ user1046037 확인 : pastebin.com/mpd3ujw2 . 분명히 모든 빈 구조체는 동일한 메모리 주소를 가리 킵니다. 그러나 변수에 포인터를 저장하고 싶을 때 그 복사본 (또는 구조체?)을 만들 것입니다.
nyg

흥미롭지 만 두 번 인쇄하면 다른 메모리 주소를 인쇄합니다. 위의 답변도 마찬가지입니다.
user1046037

@ user1046037 무슨 의미인지 잘 모르겠습니다. 코드가 있습니까? (항상 같은 메모리 주소를 얻습니다)
nyg

15

참조 유형 :

  • ID를 나타내는 참조 유형의 메모리 주소를 얻는 것이 좋습니다.
  • === 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

가치 유형 :

  • 값 유형의 메모리 주소를 가져와야하는 것은 그다지 중요하지 않으며 (값이므로) 값의 동등성에 더 중점을 둡니다.

12

이것을 사용하십시오 :

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

" MyClass?"이 CVarArg를 준수하지 않는다는 컴파일러 불만 이 표시되면 할 수 있습니다 extension Optional : CVarArg { }. 그렇지 않으면 이것은 다른 답변의 모든 "안전하지 않은"광기없이 주소를 인쇄하는 것으로 보입니다.
Devin Lane

var _cVarArgEncoding: [Int]on 구현이 필요합니다 CVarArg. 어떻게 구현해야하는지 명확하지 않습니다.
Yuchen Zhong

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...

1
다운 보트와 함께 이유를 설명하는 의견을 함께 보내주십시오. 따라서 저와 다른 사람들이 왜 이것이 나쁜 해결책인지 알고 있습니다 :)
Ben Leggiero

1
간단하고 깔끔합니다!
badhanganesh 2012 년

9

스위프트 5

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

이 답변은 잘못되었습니다. 같은 클래스의 두 인스턴스를 만들면 두 인스턴스에 대해 동일한 메모리 주소가 반환됩니다. Unmanaged.passUnretained(myObject).toOpaque()대신 제대로 작동합니다.
Padraig

@Padraig 감사합니다. 코드가 업데이트되었습니다. 슬프게도 이제 AnyObject매개 변수 가 필요합니다 . Any입력 유형으로 선호 합니다.
neoneye

6

배열에 대한 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)
    }

1
내 하루를 구했다. "가장 유용한 가장 유용한 획득"배지가 있어야합니다.
Anton Tropashko

실제로 이것은 내 인쇄 방법 중 유일한 방법입니다 self?.array.
Rostyslav Druzhchenko

4

포인터 주소를 정수로 얻는 방법을 찾고 있었지만 다른 대답은 괜찮습니다.

let ptr = unsafeAddressOf(obj)
let nullPtr = UnsafePointer<Void>(bitPattern: 0)

/// This gets the address of pointer
let address = nullPtr.distanceTo(ptr) // This is Int

약간의 후속 조치.


Swift 3에 대한이 답변의 버전은 아래를 참조하십시오.
RenniePet

3

@Drew가 제공하는 답변은 클래스 유형에만 사용할 수 있습니다.
@nschum이 제공하는 답변은 구조체 유형에 대해서만 가능합니다.

그러나 두 번째 방법을 사용하여 값 유형 요소가있는 배열의 주소를 얻는 경우. Swift에서 Swift 어레이는 쓰기 중 복사이므로 C / C ++에 제어권을 넘기면 Swift가 이러한 방식으로 동작하는지 확인할 수 없습니다 ( &주소를 가져 오기 위해 사용 하는 경우). 첫 번째 방법을 대신 사용하면 자동으로 원하지 않는 것으로 변환 Array됩니다 NSArray.

내가 찾은 가장 간단하고 통일 된 방법은 lldb 명령을 사용하는 것 frame variable -L yourVariableName입니다.

또는 당신은 그들의 답변을 결합 할 수 있습니다 :

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
}

3

이것은 스위프트 3입니다.

@CharlieMonroe와 같이 주소를 정수로 얻고 싶습니다. 특히 스레드 이름을 사용할 수없는 상황에서 진단 로깅 모듈에서 스레드 ID로 사용할 Thread 개체의 주소를 원했습니다.

Charlie Monroe의 코드를 기반으로 지금까지 내가 생각해 낸 내용은 다음과 같습니다. 그러나 Swift를 처음 접하는 사람이라면 조심하십시오.

  // Convert the memory address of the current Thread object into an Int for use as a thread ID
  let objPtr = Unmanaged.passUnretained(Thread.current).toOpaque()
  let onePtr = UnsafeMutableRawPointer(bitPattern: 1)!  // 1 used instead of 0 to avoid crash
  let rawAddress : Int64 = onePtr.distance(to: objPtr) + 1  // This may include some high-order bits
  let address = rawAddress % (256 * 1024 * 1024 * 1024)  // Remove high-order bits

마지막 문장은 0x60000007DB3F와 같은 주소를 얻지 못했기 때문입니다. 마지막 명령문의 모듈로 연산은이를 0x7DB3F로 변환합니다.


3

Swift 3에 대한 나의 해결책

extension MyClass: CustomStringConvertible {
    var description: String {
        return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
    }
}

이 코드는 기본 설명과 같은 설명을 만듭니다. <MyClass: 0x610000223340>


2

이것은 가장 빠르거나 안전한 방법이 아닙니다. 그러나 그것은 나를 위해 작동합니다. 그러면 nsobject 하위 클래스가이 속성을 채택 할 수 있습니다.

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

의견을 주셔서 감사합니다 Jeff, 나는 대답을 업데이트합니다
Charlton Provatas

1
신경 쓰지 마! 내 실수 였어! 코드는 순수한 Swift 클래스에서 잘 작동합니다. 실수해서 죄송합니다.
Jeff
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.