[NSDictionary objectForKey] crash on x64
[NSDictionary objectForKey] crash on x64
- Subject: [NSDictionary objectForKey] crash on x64
- From: Cosmin Apreutesei <email@hidden>
- Date: Fri, 11 Jul 2014 15:56:46 +0300
Hi,
I have a strange problem.
I am using C and the objc runtime on OSX 10.9.3 to get a value from a
NSDictionary.
The objectForKey method returns an invalid pointer on x64 (not NULL,
but the same address 0x937 for _any_ valid key), but works fine on
i386.
I attached a small test case to show the problem.
Here's how to build and run the test case:
echo "on 32bit works..."
gcc -arch i386 -O2 test5.c -o test5_32 -lobjc
./test5_32
echo "on 64bit crashes..."
gcc -arch x86_64 -O2 test5.c -o test5 -lobjc
./test5
Any help would be appreciated, even to tell me that you can or can't
reproduce the problem or that you find problems with the code, or to
redirect me to a different forum/mailing list.
Thanks,
Cosmin.
#include <assert.h>
#include <stdio.h>
#include <dlfcn.h>
typedef struct objc_class *Class;
typedef struct objc_object *id;
typedef struct objc_method *Method;
typedef struct objc_selector *SEL;
struct objc_class { Class isa; };
struct objc_object { Class isa; };
typedef id (*IMP) (id, SEL, ...);
Class objc_getClass(const char *name);
SEL sel_registerName(const char *str);
Method class_getInstanceMethod(Class aClass, SEL aSelector);
IMP method_getImplementation(Method method);
IMP cimp(const char* clsname, const char* selname) {
Class cls = objc_getClass(clsname) ; assert(cls != 0);
SEL sel = sel_registerName(selname) ; assert(sel != 0);
Method method = class_getInstanceMethod(cls->isa, sel) ; assert(method != 0);
IMP imp = method_getImplementation(method) ; assert(imp != 0);
return imp;
}
IMP imp(id obj, const char* selname) {
Class cls = obj->isa ; assert(obj != 0); assert(cls != 0);
SEL sel = sel_registerName(selname) ; assert(sel != 0);
Method method = class_getInstanceMethod(cls, sel) ; assert(method != 0);
IMP imp = method_getImplementation(method) ; assert(imp != 0);
return imp;
}
#define callc(clsname, selname, ctype, ...) (((ctype)cimp(clsname, selname)) ((id)objc_getClass(clsname), sel_registerName(selname), __VA_ARGS__))
#define callc0(clsname, selname, ctype) (((ctype)cimp(clsname, selname)) ((id)objc_getClass(clsname), sel_registerName(selname)))
#define call(obj, selname, ctype, ...) (((ctype)imp (obj, selname)) (obj, sel_registerName(selname), __VA_ARGS__))
#define call0(obj, selname, ctype) (((ctype)imp (obj, selname)) (obj, sel_registerName(selname)))
int main() {
setvbuf(stdout, NULL, _IONBF, 0);
dlopen("/System/Library/Frameworks/Foundation.framework/Foundation", RTLD_GLOBAL);
{
//making a NSNumber from scratch works...
id n = callc("NSNumber", "numberWithDouble:", id (*) (id, SEL, double), 12345); //make a NSNumber with value 12345
printf("%p\n", (void*)n); //note the high address
double x = call0(n, "doubleValue", double (*) (id, SEL)); //get back the value
printf("%f\n", x); //12345
}
//but getting a NSNumber from the dictionary below segfaults on 64bit (works on 32bit)...
const char* path = "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/Frameworks/HIServices.framework/Versions/Current/Resources/cursors/resizenorthwestsoutheast/info.plist";
//create a dictionary from the contents of the info.plist file
id spath = callc("NSString", "stringWithUTF8String:", id (*) (id, SEL, const char*), path); //make a NSString with the value of `path`
id d = callc("NSDictionary", "dictionaryWithContentsOfFile:", id (*) (id, SEL, id), spath); //make a NSDictionary with contents of `path`
//try to get the value of the key "hotx" from that dictionary
id s = callc("NSString", "stringWithUTF8String:", id (*) (id, SEL, const char*), "hotx"); //make a NSString with value "hotx"
id n = call(d, "objectForKey:", id (*) (id, SEL, id), s); //get the value of key "hotx"
printf("%p\n", (void*)n); //note the low address
s = callc("NSString", "stringWithUTF8String:", id (*) (id, SEL, const char*), "hoty"); //make a NSString with value "hoty"
n = call(d, "objectForKey:", id (*) (id, SEL, id), s); //get the value of key "hoty"
printf("%p\n", (void*)n); //note the same low address !!! what's going on here???
double x = call0(n, "doubleValue", double (*) (id, SEL)); //crash, of course...
printf("%f\n", x); //should be 9
return 0;
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden