দ্রুত পরিবর্তনশীল মেমরি ঠিকানা মুদ্রণ


165

[NSString stringWithFormat:@"%p", myVar]নতুন সুইফট ভাষায় ওজেক্টিভ-সি থেকে, অনুকরণ করার উপায় কি আছে ?

উদাহরণ স্বরূপ:

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

2
ইন [NSString stringWithFormat:@"%p", myVar], myVarএকটি পয়েন্টার হতে হবে। আপনার সুইফট কোডে, strকোনও পয়েন্টার নয়। সুতরাং তুলনা প্রযোজ্য নয়।
ব্যবহারকারী 102008

5
এটি লক্ষণীয় যে, অন্তত আমি যখন এটি টাইপ করব তখন উপরের দুটি মন্তব্য ভুল are
বেন লেগিগেরো

উত্তর:


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
অনিরাপদ অ্যাড্রেসঅফ () কেবল শ্রেণির ধরণের জন্য কাজ করে (নীচে নীচের পয়েন্টগুলি দেখায়) for সুতরাং, এই উত্তরটি কেবল তখনই কার্যকর হয় যখন ফাউন্ডেশন আমদানি করা হয় এবং স্ট্রিংটি এনএসএস স্ট্রিংয়ে ব্রিজ করা হয়। সাদামাটা সুইফটে, স্ট্রিং একটি মান ধরণের এবং অনিরাপদ অ্যাড্রেসঅফ তার ঠিকানা নিতে ব্যবহার করা যাবে না (সংকলনের ত্রুটির প্রয়াসের ফলাফল)।
স্টিফেন স্কাউব

29
আমি যদি সুইফট 3 দিয়ে অপরিবর্তনীয় মানের ঠিকানা মুদ্রণ করতে চাই তবে কী হবে ? ত্রুটি withUnsafePointerফলাফল cannot pass immutable value as inout argument
আলেকজান্ডার ভ্যাসেনিন

12
যদিও এটি গৃহীত এবং সর্বাধিক ভোট দেওয়া উত্তর, তবুও এটি ভুল ফলাফল দেয় । উদাহরণ: print(self.description)প্রিন্টস <MyViewController: 0x101c1d580>, আমরা এটি একটি রেফারেন্স হিসাবে ব্যবহার করি। var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }প্রিন্ট 0x16fde4028যা স্পষ্টভাবে আলাদা ঠিকানা। কেন কেউ ব্যাখ্যা করতে পারেন?
আলেকজান্ডার ভ্যাসেনিন

4
0x101c1d580print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
বিটিডাব্লু,

8
@nyg আপনার উত্তরটি আমাকে প্রকৃত ত্রুটির কারণের জন্য একটি সূত্র দিয়েছে: UnsafePointerএটি একটি কাঠামো, সুতরাং যে ঠিকানাটি এটি নির্দেশ করছে তা মুদ্রণের জন্য আপনাকে (এবং স্ট্রাকটি নিজেই নয়) আপনাকে মুদ্রণ করতে হবে String(format: "%p", $0.pointee)!
আলেকজান্ডার ভ্যাসেনিন

213

দ্রষ্টব্য: এটি রেফারেন্স ধরণের জন্য।

সুইফট 4/5:

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

কিছু ভারের স্মৃতি ঠিকানা মুদ্রণ করে। (@ ইংকে ধন্যবাদ)


সুইফট ৩.১:

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

কিছু ভারের স্মৃতি ঠিকানা মুদ্রণ করে।



2
এক্সকোড 8.2.1 স্বতঃসংশোধন আমাকে বলছে এটি এখনprint(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
জেফ

2
সাম্যভার একটি বস্তু হলেই এটি সত্য হবে না। যদি কিছুভার কোনও স্ট্রাকের মতো মান ধরণের হয়ে থাকে তবে এটি কার্যকর হওয়ার সময় এটি আলাদা আলাদা ঠিকানা দেবে।
আউটআউই উইন্ডেন্ড

3
@ ওটঅনএ উইকএন্ড আপনি ঠিক বলেছেন, সম্ভবত যুক্তি হিসাবে পাস করার পরে কাঠামোটি অনুলিপি করা হয়েছিল। ব্যবহার Unmanagedএটা ভালো করা সম্ভব: print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
nyg

1
সুইফট 4 হিসাবে, আমি এই মুদ্রণটিও মুদ্রণ করতে সক্ষম হয়েছি - Unmanaged.passUnretained(someVar).toOpaque()(জেনেরিক নির্দিষ্টকরণের প্রয়োজন নেই)
ইং

2
সুইফট 4 উত্তরটি নিখুঁত। আপনিও যদি মুদ্রণ ছাড়াই স্ট্রিং প্রতিনিধিত্ব পেতে চান, আমি debugDescriptionএর শেষে যোগ করার পরামর্শ দিই ।
প্যাট্রিক

51

মনে রাখবেন এই উত্তরটি বেশ পুরানো ছিল। এটি বর্ণনা করে এমন অনেকগুলি পদ্ধতি আর কাজ করে না। বিশেষত .coreআর অ্যাক্সেস করা যাবে না।

তবে @ ড্র এর উত্তর সঠিক এবং সহজ:

এটি এখন স্ট্যান্ডার্ড লাইব্রেরির অংশ: অনিরাপদ অ্যাড্রেসঅফ।

সুতরাং আপনার প্রশ্নের উত্তর হ'ল:

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

এখানে আসল উত্তরটি সঠিক হিসাবে চিহ্নিত হয়েছিল (উত্তরসূরি / ভদ্রতার জন্য):

সুইফ্ট পয়েন্টারগুলিকে "আড়াল করে", তবে সেগুলি এখনও হুডের নীচে বিদ্যমান। (কারণ রানটাইমটির এটির প্রয়োজন হয়, এবং ওজেজসি এবং সি এর সাথে সামঞ্জস্যের কারণে)

তবে কয়েকটি জিনিস জানা থাকলেও প্রথমে কীভাবে একটি সুইফ্ট স্ট্রিংয়ের মেমরি ঠিকানা মুদ্রণ করবেন?

    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

এটি স্ট্যাকের উপরে থাকবে, কারণ স্ট্রিংটি রানটাইম এ তৈরি করা হয়েছিল

দ্রষ্টব্য: .ore._baseAdress নথিবদ্ধ নয়, আমি এটি ভেরিয়েবল পরিদর্শকের সন্ধানে পেয়েছি এবং এটি ভবিষ্যতে লুকিয়ে থাকতে পারে

_baseAddress সব ধরণের উপলভ্য নয়, এখানে সিআইএনটি সহ আরও একটি উদাহরণ রয়েছে

    var testNumber : CInt = 289
    takesInt(&testNumber)

takesIntএটির মতো সি হেল্পার ফাংশনটি কোথায়

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

সুইফ্ট প্রান্তে, এই ফাংশনটি takesInt(intptr: CMutablePointer<CInt>)তাই একটি সিআইএনটিতে সিএমটেবলপয়েন্টার নিয়ে যায় এবং আপনি এটির সাথে & বর্ণের সাহায্যে এটি পেতে পারেন

ফাংশন মুদ্রণ করে 0x7fff5fbfed98, এই মেমরি ঠিকানার একটিতে আপনি 289 পাবেন (হেক্সাডেসিমাল স্বরলিপিতে)। আপনি এর সামগ্রীটি এর সাথে পরিবর্তন করতে পারেন*intptr = 123456

এখন, আরও কিছু বিষয় জানতে হবে।

স্ট্রিং, দ্রুতগতিতে, একটি প্রাথমিক ধরণের, কোনও বস্তু নয়।
সিআইএনটি একটি সুইফট টাইপ যা সি ইন্ট টাইপ-এ ম্যাপ করা হয়।
আপনি যদি কোনও জিনিসের মেমরি ঠিকানা চান তবে আপনাকে আলাদা কিছু করতে হবে।
সুইফ্টের কয়েকটি পয়েন্টার প্রকার রয়েছে যা সি এর সাথে ইন্টারেক্ট করার সময় ব্যবহার করা যেতে পারে এবং আপনি সেগুলি সম্পর্কে এখানে পড়তে পারেন: সুইফট পয়েন্টার প্রকারগুলি
আরও জানুন, রূপান্তর কীভাবে রূপান্তর করতে হয় তা বুঝতে আপনি তাদের ঘোষণার অন্বেষণ (সেন্টিমিড + টাইপ ক্লিক করুন) সম্পর্কে আরও জানতে পারবেন অন্য পয়েন্টার এক প্রকার

    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 এই বাস্তবায়ন সহ আমি তৈরি করা একটি সি সহায়ক সহায়ক ফাংশন

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

আবার, মুদ্রিত ঠিকানার একটি উদাহরণ: 0x6000000530b0এবং আপনি যদি মেমরি পরিদর্শকের মাধ্যমে যান তবে আপনি আপনার এনএসএস স্ট্রিং পাবেন

আপনি সুইফ্টের পয়েন্টারগুলির সাথে একটি জিনিস করতে পারেন (এটি এমনকি আউটআউট প্যারামিটারগুলি দিয়েও করা যেতে পারে)

    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

হ্যাঁ, পয়েন্টারটি বাইরে বেরিয়ে যেতে হবে তবে কেবলমাত্র আপনি উল্লেখ করেছেন এমন সামঞ্জস্যতার কারণে নয়। অপারেটিং সিস্টেম দ্বারা ব্যবহৃত পয়েন্টারগুলি। ভাষাটি যদি উচ্চ-স্তরের ভাষা হয় তবে অপারেটিং সিস্টেমের ইঞ্জিনে যে কোনও সময়ে পয়েন্টারগুলির যে কোনও ভাষায় উপস্থিত থাকতে হবে।
হোলএক্স

আমি বলেছিলাম "সামঞ্জস্যের কারণে এবং কারণ রানটাইমের এটি প্রয়োজন" :-) দ্বিতীয় বিবৃতিটি আপনি যা বলছেন তা
পুনরুদ্ধার করে

আমি ধরে নিলাম এটি আর প্রযোজ্য নয়?
অ্যালেক্সারসন

হ্যাঁ. আমি @ ড্র থেকে সঠিক উত্তরটি এতে সম্পাদনা করেছি।
রোগ

@ লম্বাক্স আমরা কেবল রেফারেন্স টাইপের ঠিকানা প্রিন্ট করতে পারি? আমি ভেরিয়েবলের ঠিকানা মুদ্রণ করতে পারি না?
অভিমন্যু আরিয়ান

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

( সম্পাদনা করুন: সুইফট ১.২ এখন একটি অনুরূপ ফাংশন অন্তর্ভুক্ত)unsafeAddressOf ))

উদ্দেশ্য-সি এ হবে [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

উদ্দেশ্য সি ইন এই হবে [NSString stringWithFormat:@"%p", &o]বা [NSString stringWithFormat:@"%p", &i]

sকাঠামোযুক্ত সুতরাং যদি sঅন্য ভেরিয়েবলের জন্য বরাদ্দ করা হয় s2, মানটি অনুলিপি করা হবে এবং এর জন্য প্রাপ্ত ঠিকানাটি s2ভিন্ন হবে।

এটি কীভাবে একসাথে ফিট হয় (পয়েন্টার পুনর্নির্মাণ)

উদ্দেশ্য-সি এর মতো, এর সাথে দুটি পৃথক ঠিকানা যুক্ত রয়েছে o । প্রথমটি হল বস্তুর অবস্থান, দ্বিতীয়টি হল বস্তুর রেফারেন্সের অবস্থান (বা পয়েন্টার)।

হ্যাঁ, এর অর্থ হ'ল 0x7fff5fbfe658 ঠিকানার সামগ্রীটি 0x6100000011d0 নম্বর হিসাবে ডিবাগারটি আমাদের বলতে পারেন:

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

সুতরাং, স্ট্রিংগুলি স্ট্রাক্ট হওয়া ব্যতীত, অভ্যন্তরীণভাবে এটি সমস্ত (jজেক্টিভ- সি) মতো একইভাবে কাজ করে।

(এক্সকোড 6.3 হিসাবে বর্তমান)


হুম। কোনও সামগ্রীর সম্পত্তির স্ট্যাক ঠিকানা পাওয়া সামঞ্জস্যপূর্ণ নয়। কোন ধারনা? এই টুকরোটি দেখুন!
অ্যালেক্সারসন

বস্তুর বৈশিষ্ট্য স্তূপে নয়, স্তূপে রয়েছে। আপনি যখন কোনও শ্রেণিবদ্ধের সম্পত্তি কোনও অনিরাপদ পয়েন্টার হিসাবে পাস করেন, সুইফ্টটি প্রথমে প্রথমে মানটি অনুলিপি করে এবং আপনি অনুলিপিটির ঠিকানা পান। আমি সন্দেহ করি যে এটি সি কোডটিকে অবজেক্টের ইন্টারফেসকে অবরুদ্ধ করা এবং অসামঞ্জস্যপূর্ণ অবস্থার কারণ হতে পারে না। আমি জানি না যে এর আশেপাশে কোনও উপায় আছে কিনা।
nschum


20

টি এল; ডিআর

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
*/

( সংক্ষেপে )


সুইফটে আমরা মান ধরণের (স্ট্রাকচার) বা রেফারেন্স ধরণের (ক্লাস) সাথে হয়। যখন করছেন:

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

কিছু ঠিকানা ম্যাসেজ X এ বরাদ্দ করা হয়েছে, এবং এই ঠিকানায় আমরা 42 মানটি পেয়ে যাব Do কাজটি &nএক্সকে সম্বোধন করার জন্য একটি পয়েন্টার তৈরি করে, সুতরাং &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 এ যেখানে শ্রেণীর উদাহরণ ডেটা রয়েছে এবং
  • দশম ঠিকানাতে যেখানে শ্রেণীর উদাহরণ রেফারেন্সটি অবস্থিত।

যেমনটি বলা হয়েছে, ক্লাসগুলি রেফারেন্সের ধরণসমূহ: সুতরাং মানটি cঠিকানা X এ অবস্থিত, যেখানে আমরা Y এর মান খুঁজে পাই And এবং 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 (বার) হয়।

উভয় ক্ষেত্রেই, ব্যবহার করে &nবা&c আমাদের ঠিকানা এক্স মান ধরনের যে আমরা কি চাই, কিন্তু রেফারেন্স ধরনের জন্য নয় দেব।

যখন করছেন:

let referencePointer = UnsafeMutablePointer<C>(&c)

আমরা রেফারেন্সে একটি পয়েন্টার তৈরি করি, অর্থাত্ একটি পয়েন্টার যা এক্সকে সম্বোধন করে 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 এর ঠিক ঠিকায় আমরা ওয়াই ঠিকানা খুঁজে পাব (যা আমরা চাই এটি) এটি পেতে আমরা নিম্নলিখিতটি করতে পারি:

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)

আমি আশা করি এটি সাহায্য করেছে ... এটি আমার পক্ষে হয়েছে 😆


কেবলমাত্র লক্ষ্য করা গেছে যে একই স্ট্রাক্টের MemoryLocationঠিকানাটি 2 টি পৃথক ঠিকানা উত্পাদন করার জন্য 2 টি পৃথক উদাহরণের মাধ্যমে মুদ্রণের চেষ্টা করার সময় ।
ব্যবহারকারী 1046037

@ user1046037 ধন্যবাদ, ক্লাস আরম্ভের জন্য পরিবর্তন করেছে। আমি দুটি পৃথক ঠিকানাও পাই, তবে কেবল যখন আমি একটি খালি কাঠামো ব্যবহার করি। খালি কাঠামো ব্যবহার করা আমাকে সর্বদা অদ্ভুত ফলাফল দেয়। আমার অনুমান সংকলকটি কিছু অপ্টিমাইজেশন করে ...
nyg

@ ব্যবহারকারী 1046037 চেক করুন: পেস্টবিন . com/ এমপিডি 3 ইউজওয়ু 2 । স্পষ্টতই, সমস্ত খালি কাঠামো একই মেমরি ঠিকানার দিকে নির্দেশ করে। যাইহোক, আমরা যখন পয়েন্টারটি একটি ভেরিয়েবলে সঞ্চয় করতে চাই তখন এটি এর একটি অনুলিপি তৈরি করবে (বা স্ট্রাক্টের?) ...
nyg

এটি আকর্ষণীয় তবে দু'বার মুদ্রিত হলে এটি বিভিন্ন মেমরি ঠিকানা মুদ্রণ করে। উপরের উত্তরগুলির ক্ষেত্রেও একই অবস্থা।
ব্যবহারকারী 1046037

@ user1046037 আমি নিশ্চিত না আপনি কী বলতে চাইছেন তা আমি বুঝতে পেরেছি, আপনার কিছু কোড আছে? (আমি সর্বদা একই মেমরি ঠিকানা
পাই

15

রেফারেন্সের প্রকারগুলি:

  • কোনও রেফারেন্স টাইপের মেমরি ঠিকানাটি যেমন পরিচয় উপস্থাপন করে তা পেতে এটি উপলব্ধি করে।
  • === আইডেন্টিটি অপারেটর একই পদার্থের নির্দেশ করে 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?" সিভিআরআর্গের সাথে সামঞ্জস্য না করে সে সম্পর্কে কোনও সংকলক অভিযোগ পান তবে আপনি এটি করতে পারেন extension Optional : CVarArg { }। অন্যথায় এটি অন্যান্য উত্তরের সমস্ত "অনিরাপদ" উন্মাদনা ছাড়াই ঠিকানা মুদ্রণ করে বলে মনে হচ্ছে।
ডেভেন লেন

এটা তোলে বাস্তবায়ন প্রয়োজন var _cVarArgEncoding: [Int]উপর CVarArg। কীভাবে এটি প্রয়োগ করা উচিত তা পরিষ্কার নয়।
ইউচেন ঝং

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
দয়া করে কোনও ডাউনভোটের সাথে কেন একটি মন্তব্য সহ একটি মন্তব্য করুন, সুতরাং আমি এবং অন্য যে কেউ এখানে আসবেন তারা কেন জানি এটি একটি দুর্বল সমাধান নয় :)
বেন লেগজিও

1
সরল এবং ঝরঝরে!
বদঘনেশ

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

এই উত্তরটি ভুল। আপনি যদি একই শ্রেণীর দুটি উদাহরণ তৈরি করেন তবে উভয় দৃষ্টান্তেই একই মেমরি ঠিকানা ফিরে আসবে'll Unmanaged.passUnretained(myObject).toOpaque()পরিবর্তে সঠিকভাবে কাজ করে।
পাদরাইগ

@ প্যাড্রাইগ ধন্যবাদ, আমি আপনার কোডটি আপডেট করেছি। দুঃখজনকভাবে এটি এখন একটি AnyObjectপ্যারামিটার লাগে । আমি Anyইনপুট টাইপ হিসাবে পছন্দ করব ।
নিউনি

6

অ্যারে সম্পর্কে সুইফট 4 এ:

    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
আমার দিন বাঁচিয়েছে। একটি ব্যাজ থাকা উচিত "সবচেয়ে কার্যকর সাম্প্রতিক এত অধিগ্রহণ"
আন্তন ট্রপ্যাশকো

আসলে, এটি আমার মুদ্রিত একমাত্র পন্থা self?.array
রোস্তিস্লাভ দ্রুজচেনকো

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

একটু ফলোআপ।


এই উত্তরটির একটি সংস্করণ সুইফট 3 এর জন্য নীচে দেখুন
রেনিপেট

3

@ অঙ্কিত উত্তরটি কেবল শ্রেণির জন্য ব্যবহার করা যেতে পারে।
@ এনএসচামের উত্তরটি কেবল স্ট্রাক্ট ধরণের জন্যই হতে পারে।

তবে আপনি যদি মান পদ্ধতির উপাদান সহ কোনও অ্যারের ঠিকানা পেতে দ্বিতীয় পদ্ধতি ব্যবহার করেন। সুইফট পুরো অ্যারেটি অনুলিপি করবে কারণ সুইফ্ট অ্যারেতে অনুলিপি অনুলিপি হয় এবং সি / সি ++ এর উপর নিয়ন্ত্রণ সরিয়ে দেওয়ার পরে সুইফট এটি এইভাবে আচরণ করে তা নিশ্চিত করতে পারে না ( &ঠিকানাটি ব্যবহার করে যা ট্রিগার হয় )। এবং পরিবর্তে আপনি যদি প্রথম পদ্ধতি ব্যবহার করেন তবে এটি স্বয়ংক্রিয়ভাবে রূপান্তরিত 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 এর জন্য।

@ চর্লিমনরোয়ের মতো আমি পূর্ণসংখ্যা হিসাবে ঠিকানাটি পেতে চাই। বিশেষত, আমি ডায়াগনস্টিক লগিং মডিউলটিতে একটি থ্রেড আইডি হিসাবে ব্যবহারের জন্য একটি থ্রেড অবজেক্টের ঠিকানা চেয়েছিলাম, যেখানে কোনও থ্রেডের নাম উপলব্ধ ছিল না।

চার্লি মনরো এর কোডের উপর ভিত্তি করে, আমি এখন পর্যন্ত যা নিয়ে এসেছি তা এখানে। তবে সাবধান, আমি সুইফটে খুব নতুন, এটি সঠিক নাও হতে পারে ...

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

সুইফট 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

এটি অবশ্যই সবচেয়ে দ্রুত বা নিরাপদ উপায় নয়। তবে এটি আমার পক্ষে কাজ করে। এটি কোনও এনসোবজেক্ট সাবক্লাসকে এই সম্পত্তিটি গ্রহণ করার অনুমতি দেবে।

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

জেফের প্রতিক্রিয়াটির জন্য ধন্যবাদ, আমি উত্তরটি আপডেট করব
চার্লটন প্রোভ্যাটাস

1
কিছু মনে করো না! এটা আমার ভুল ছিল! আপনার কোডটি খাঁটি সুইফ্ট শ্রেণীর সাথে সূক্ষ্মভাবে কাজ করে। ভুলের জন্য দুঃখিত.
জেফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.