-
-
Save landonf/938633 to your computer and use it in GitHub Desktop.
objc_msgSend gotchas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
$ gcc --version | |
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3) | |
Copyright (C) 2007 Free Software Foundation, Inc. | |
This is free software; see the source for copying conditions. There is NO | |
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
$ clang --version | |
Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn) | |
Target: x86_64-apple-darwin10 | |
Thread model: posix | |
gcc -arch x86_64 banana.m -framework Foundation && ./a.out => pear | |
gcc -arch i386 banana.m -framework Foundation && ./a.out => banana | |
clang -arch x86_64 banana.m -framework Foundation && ./a.out => banana | |
clang -arch i386 banana.m -framework Foundation && ./a.out => banana | |
*/ | |
#import <Foundation/Foundation.h> | |
#import <objc/runtime.h> | |
#import <objc/message.h> | |
static int magic() | |
{ | |
return 36; // (0x0000000100000ca3 - 0x0000000100000c13) / 4 | |
} | |
static id pear() | |
{ | |
__asm__("nop"); | |
return @"pear"; | |
} | |
// The method isn't variadic itself, so the IMP also shouldn't be | |
static id banana(id self, SEL _cmd) | |
{ | |
return @"banana"; | |
} | |
@interface Fruit : NSObject | |
@end | |
@implementation Fruit | |
- (id) apple | |
{ | |
return @"apple"; | |
} | |
@end | |
int main (int argc, char const *argv[]) | |
{ | |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
Method apple = class_getInstanceMethod([Fruit class], @selector(apple)); | |
method_setImplementation(apple, (IMP)banana); | |
Fruit *fruit = [[[Fruit alloc] init] autorelease]; | |
int n = magic(); | |
// The following will emit identical code | |
printf("%s\n", [[fruit apple] UTF8String]); | |
printf("%s\n", [(*(NSString *(*)(id, SEL))objc_msgSend)(fruit, @selector(apple)) UTF8String]); | |
// This will not emit correct code | |
objc_msgSend(fruit, @selector(apple)); | |
[pool drain]; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment