Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get class from instance hex in Objective-C

When seeing an instance variable's address in the debugger, how can one get the class by entering in the given memory address?

I know that the opposite (getting the address from an instance) is possible with p someObjectInstance in the debugger or NSLog(@"%p", someObjectInstance); from within the code. Is there a similar way to do this the other way around?

like image 963
Old McStopher Avatar asked Jul 13 '12 01:07

Old McStopher


3 Answers

In the debugger you can use po on an address that you suspect is a valid Objective-C object. For example, in a run of one of my programs I know that 0x9549ee0 points to a UIFont object.

Using po I see the following:

(gdb) po 0x9549ee0
<UICFFont: 0x9549ee0> font-family: "Helvetica"; font-weight: normal; font-style: normal; font-size: 14px

This will print out the same information you would have obtained using:

NSLog(@"%@", someObject);

that is to say the result of [someObject description]. This often contains more useful information that merely the class name (as can be seen from the example above).

As, Richard J. Ross III, mentions you should be careful doing this. The debugger can often tell if the address is invalid, for example:

(gdb) po 0x9449ee0
0x9449ee0 does not appear to point to a valid object.

but the way it does this is not foolproof. If you were to do it in code in your program, it would likely crash.

Oh and of course you can use po directly on a variable too:

(gdb) po font
<UICFFont: 0x9549ee0> font-family: "Helvetica"; font-weight: normal; font-style: normal; font-size: 14px

Hope this helps.

like image 179
idz Avatar answered Nov 17 '22 01:11

idz


What you are asking for is VERY unsafe. Accessing an unknown memory location is generally a bad idea, but since you asked:

EDIT: If inside gdb or lldb, you can do the following:

po [(id)(0xDEADBEEF) class]

If running from code, however, use the following;

NSString *input = @"0xFAFAFA";

unsigned address = UINT_MAX; // or UINT_MAX
[[NSScanner scannerWithString:input] scanHexInt:&address];

if (address == UINT_MAX)
{
    // couldn't parse input...
    NSLog(@"failed to parse input");
    return 0;
}

void *asRawPointer = (void *) (intptr_t) address;
id value = (__bridge id) asRawPointer;

// now do something with 'value'
NSLog(@"%@", [value class]);
like image 20
Richard J. Ross III Avatar answered Nov 17 '22 01:11

Richard J. Ross III


Right click in the debug area and select Debug Area Help->Viewing Memory Locations

Or in the Xcode documentation go to

Xcode Developer Library->Xcode->IDEs->Debug Area Help-> Viewing Memory Locations

like image 1
JordanC Avatar answered Nov 17 '22 02:11

JordanC