Alex Gray
Alex Gray

Reputation: 16463

How to dereference an Objective-C object via its pointer/memory address?

So, it is very easy to get an object pointer's "memory address", á la..

id x = @"obj"; printf("'x' is at: %p", x);

'x' is at: 0x100b60048

Amazingly, I cannot seem to find ANY reference as to how to perform the "reverse" operation. ie. get a reference to an object pointer, either via the hex int pointer address, or it's string representation ...

NSString  * ptr = @"0x100b60048";
unsigned   addr = 0;
NSScanner * scn = [NSScanner scannerWithString:ptr];
[scn scanHexInt:&addr];

I did come across the following "way", but it a) doesn't work (it crashes) and b) irks the fragile sensibilities of the compiler (aka, it emits warnings, lol).

id z = (__bridge id)((void*)addr);

So, what is "right", modern, ARC-compatible way to do this?

Upvotes: 2

Views: 1925

Answers (3)

Alex Gray
Alex Gray

Reputation: 16463

OK, well I did figure out a relatively painless way to do this, so I'll post it here for hazing / nitpicking and even, < gasp > ... possible acceptance ... Using the original question's variables...

/// this requires a "0x" formatted hex string                                              
ptr = [ptr hasPrefix:@"0x"] ? ptr :
      [@"0x" stringByAppendingString:ptr];

uintptr_t hex = strtoull(ptr.UTF8String, NULL, 0);
    id gotcha = (__bridge id)(void *)hex;

Upvotes: 0

bbum
bbum

Reputation: 162712

So, what is "right", modern, ARC-compatible way to do this?

The right way? Don't do it.

For an object to remain in memory in an ARC'd application, there needs to be a strong reference to said object (or you have to do something really nasty with the CF APIs). And any pointer-in-a-string will only be valid during the lifetime of the app; quit and restart? All addresses are now bogus.

So, if you really want to refer to a random object in a string, then do this:

  • stick the object in a dictionary with an NSNumber or an NSString as a key (you can even use the address of the object as the value but I would recommend against it because addresses don't survive app re-launches and you'll probably someday want to persist that dictionary)
  • when you parse the string, extract the key and look up the object

That way, you'll never have to cast between int and ptr, you won't have to use a ton of dangerous typecasting to quiet the compiler and your code will be ARC compatible.

Upvotes: 2

Dare
Dare

Reputation: 2587

So this works. That being said, I would be very uncomfortable relying on this in a project of mine. If that variable gets released before you scan its address, who knows what you're going to get. In that respect, I guess that breaks the "ARC compatible" criterion because who knows when that reference will get released which makes this very dangerous. Also, type safety is totally out the window.

NSString *pointer = @"test";
NSString *address = [NSString stringWithFormat:@"%p",pointer];

NSString *retrievedObject;
sscanf([address cStringUsingEncoding:NSUTF8StringEncoding], "%p", &retrievedObject);

Upvotes: 1

Related Questions