This is what I'm referring to:
From what I've read, an objc_msgSend is essentially what is happening at the c level when you send an Objective-C message, and this setting set to Yes ensures that the message being sent has the same number of arguments as the the receiver is expecting.
Is this correct? Also what are the advantages and disadvantages to setting this to Yes or No? Should I only set this to Yes in development and No in production?
You are essentially correct, yes.
Apple sets it to Yes by default because it helps to find errors faster. The only reason to set it to No would be because you are compiling legacy code that hasn't been updated to compile cleanly with this option on.
"Enable Strict Checking of objc_msgSend Calls" is a compile time check, not run time, so there is no benefit to turning it off in production.
There's a presentation "What's new in LLVM" on Apple's website (text of the presentation is here).
It looks like the compiler will now (optionally) strictly check the types of calls to obj_msgSend. You will have use a correctly-typed function pointer in place of directly calling objc_msgSend.
Example given:
#include <objc/message.h>
void foo(void *object) {
typedef void (*send_type)(void *, SEL, int);
send_type func = (send_type)objc_msgSend;
func(object, sel_getUid("foo:"), 5);
}
Related
I've tried to use OBJC_PRINT_VTABLE_IMAGES and OBJC_PRINT_VTABLE_SETUP environmental variables on Objective-C executable in order to learn about vtable mechanism in Objective-C objects. Unfortunately the mentioned environment variables have no effect on console output, despite the fact that runtime acknowledged that the variables were set:
ยป OBJC_PRINT_OPTIONS=1 OBJC_PRINT_VTABLE_IMAGES=YES /Applications/TextEdit.app/Contents/MacOS/TextEdit
objc[41098]: OBJC_PRINT_OPTIONS is set
objc[41098]: OBJC_PRINT_VTABLE_IMAGES is set
I've tried to use both variables on executables provided by system (TextEdit) and my own. With no effect.
Whole vtable mechanism in Objective-C objects is obscure. It's hard to find information about this mechanism on Apple pages. There is some info from other sources, but no official documentation:
http://www.sealiesoftware.com/blog/archive/2011/06/17/objc_explain_objc_msgSend_vtable.html
http://cocoasamurai.blogspot.com/2010/01/understanding-objective-c-runtime.html
Why these variables are not working? Does vtables in current version of Objective-C are deprecated?
In this case, the answer is pretty straightforward - vtable dispatch is no longer optimized in the objective-c runtime, and was probably a bad idea in the first place.
vtable-based dispatch was one of the first attempts to speed up frequent calls in the objective-c runtime, but note that it predates the current method caching solution. The problem with using a fixed set of selectors as in the vtable solution not only means increased memory for every class in the runtime, but it also means that if you're using an architecture which doesn't result in isEqualToString: being called frequently, for example, you now have a completely wasted pointer for EVERY class in the runtime that overrides ONE of those selectors. Whoops.
Also, note that Vtable dispatch by design couldn't work on 32-bit architectures, which meant that once the iOS SDK was released, and 32bit was again a reasonable target for objective-c, that optimization simply couldn't work.
The relevant documentation that I can find for this is in objc-abi.h:
#if TARGET_OS_OSX && defined(__x86_64__)
// objc_msgSend_fixup() is used for vtable-dispatchable call sites.
OBJC_EXPORT void objc_msgSend_fixup(void)
__OSX_DEPRECATED(10.5, 10.8, "fixup dispatch is no longer optimized")
__IOS_UNAVAILABLE __TVOS_UNAVAILABLE __WATCHOS_UNAVAILABLE;
Nowadays, there aren't many vestigial fragments of vtable dispatch left in the runtime. A quick grep over the codebase shows a few places in objc-runtime-new.mm:
#if SUPPORT_FIXUP
// Fix up old objc_msgSend_fixup call sites
for (EACH_HEADER) {
message_ref_t *refs = _getObjc2MessageRefs(hi, &count);
if (count == 0) continue;
if (PrintVtables) {
_objc_inform("VTABLES: repairing %zu unsupported vtable dispatch "
"call sites in %s", count, hi->fname());
}
for (i = 0; i < count; i++) {
fixupMessageRef(refs+i);
}
}
ts.log("IMAGE TIMES: fix up objc_msgSend_fixup");
#endif
And
*********************************************************************
* fixupMessageRef
* Repairs an old vtable dispatch call site.
* vtable dispatch itself is not supported.
**********************************************************************/
static void
fixupMessageRef(message_ref_t *msg)
Which pretty clearly indicates that it's not supported.
See also, the method stub for it (if you were to do it without a compiler generated call-site), found in objc-msg-x86_64.s:
ENTRY _objc_msgSend_fixup
int3
END_ENTRY _objc_msgSend_fixup
Where int3 is the SIGTRAP instruction, which would cause a crash if a debugger isn't attached (usually).
So, while vtable dispatch is an interesting note in the history of objective-c, it should be looked back as little more than an experiment when we weren't quite familiar with the best ways to optimize common method calls.
What is the best practice for mixing Objective-C ARC with longjmp?
I am using Lua as scripting language, and my platform exports custom library for scripts. Entry points do check arguments with luaL_checkinteger(L, 2) (among others), which, in turn, may call luaL_typerror(L, 2, ...), that is implemented in Lua with setjmp/longjmp. As far as I know, ARC simply auto-generates retain/release code, but what happens if it longjmps out of scope? Will this code leak on mistyped arguments?
static int
set_tag(lua_State *L)
{
NSControl *control = (__bridge NSControl *)lua_topointer(L, 1);
[control setTag:(NSInteger)luaL_checkinteger(L, 2)]; // may longjmp!
return 0;
}
In the snippet above, control will be temporarily retained by ARC, but with longjmps uncatchable nature, corresponding release call may never happen. On the other hand, all arguments may be checked before assigning to control variable.
static int
set_tag(lua_State *L)
{
NSInteger tag = luaL_checkinteger(L, 2); // may longjmp!
NSControl *control = (__bridge NSControl *)lua_topointer(L, 1);
[control setTag:tag];
return 0;
}
Does it resolve [potential] leak above? Are there better ways to do this?
UPDATE: longjmp only unwinds to Lua internals, and never crosses any system code, except for Lua source (which is aware), and my entry points (which I hope are aware).
I'm pretty sure that second snippet does right, but I need kind of formal proof.
LATE UPDATE:
LuaJIT implements dwarf2-compatible errors, so they are just like C++ exceptions. Pass -fobjc-arc-exceptions compiler flag to arc-enabled sources with Lua code and any retained object will be released on any lua_error. Nothing to worry about now! You are still not allowed to throw errors across Cocoa runtime, though.
I recall that original Lua may be compiled with exceptions too, but I'm not sure.
Doesn't really matter if ARC is in use or not; any setjmp/longjmp that jumps over any frame of code from the system frameworks will yield undefined behavior (for the same reason that exceptions cannot be used for recoverable error handling).
So, yes, that code might leak. Might because it depends on whether the compiler emits a retain/release in that block and where. Might also because whether the compiler emits retain/release will be impacted by the optimization level and, over time, the version of the compiler.
longjmp only unwinds to Lua internals, and never crosses any system
code, except for Lua source (which is aware), and my entry points
(which I hope are aware).
That is helpful. As long as you structure your entry points such that they never intermingle system scope with Lua jumpable scopes, you should be OK. I would recommend turning off ARC in the source files where you have to manage this (and, of course, put the ObjC->Lua interface into a nicely encapsulated bit of implementation so the rest of your code can be ARC clean).
Consider, though, that there is non-obvious risk:
for(id x in anArray) {
... lua call that causes longjmp ...
}
The above would cause lua to "jump over" system code. Same goes for enumerateWithBlock:, KVO, Notification handlers, etc...
You're going to have to think very very carefully about every potential stack trigger by a call from Lua into your code. If that call triggers any kind of automated behavior on the part of the system that could then call Lua API that could trigger a longjmp, all bets are off.
longjmp() may cause crashes or leaks in ARC. Arranging the code so longjmp() and ARC don't interfere is difficult.
If the longjmp() is only for a fatal error path and you expect to halt the process in response then you may be able to ignore the problem. This is what ARC does with C++/ObjC exceptions by default. ARC code is expected to leak when exceptions are thrown. There's a compiler option to enable the clean up code for exceptions, but that hurts performance.
If the longjmp() is not a process-killing error then your best option is to turn off ARC in any code that may be skipped by a longjmp() call.
Background as I understand it: Objective-C method invocations are basically a C function call with two hidden parameters (the receiver and the selector). The Objective-C runtime contains a function named objc_msgSend() that allows to invoke methods that way. Unfortunately, when a function returns a struct some special treatment may be needed. There are arcane (some might say insane) rules that govern whether the structure is returned like other values or whether it's actually returned by reference in a hidden first argument. For Objective-C there's another function called objc_msgSend_stret() that must be used in these cases.
The question: Given a method, can NSMethodSignature or something else tell me whether I have to use objc_msgSend() or objc_msgSend_stret()? So far we have found out that NSMethodSignature knows this, it prints it in its debug output, but there doesn't seem to be a public API.
In case you want to respond with "why on earth would you want to do that?!", please read the following before you do: https://github.com/erikdoe/ocmock/pull/41
Objective-C uses the same underlying ABI for C on a given architecture, because methods are just C functions with implicit self and _cmd arguments.
In other words, if you have a method:
- (SomeStructType)myMeth:(SomeArgType)arg;
then really this is a plain C function:
SomeStructType myMeth(id self, SEL _cmd, SomeArgType arg);
I'm pretty sure you already know that, but I'm merely mentioning it for other readers.
In other words, you want to ask libffi or any kind of similar library how SomeStructType would be returned for that architecture.
NSMethodSignature has a -methodReturnType that you can inspect to see if the return type is a struct. Is this what you're trying to do?
From http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html:
The rules for which struct types return in registers are always
arcane, sometimes insane. ppc32 is trivial: structs never return in
registers. i386 is straightforward: structs with sizeof exactly equal
to 1, 2, 4, or 8 return in registers. x86_64 is more complicated,
including rules for returning floating-point struct fields in FPU
registers, and ppc64's rules and exceptions will make your head spin.
The gory details are documented in the Mac OS X ABI Guide, though as
usual if the documentation and the compiler disagree then the
documentation is wrong.
If you're calling objc_msgSend directly and need to know whether to
use objc_msgSend_stret for a particular struct type, I recommend the
empirical approach: write a line of code that calls your method,
compile it on each architecture you care about, and look at the
assembly code to see which dispatch function the compiler uses.
For years I've been following a great pattern called Target-Action which goes like this:
An object calls a specified selector on a specified target object when the time comes to call. This is very useful in lots of different cases where you need a simple callback to an arbitrary method.
Here's an example:
- (void)itemLoaded {
[specifiedReceiver performSelector:specifiedSelector];
}
Under ARC it now turns out that doing something like this all of a sudden became dangerous.
Xcode throws a warning that goes like this:
PerformSelector may cause a leak because its selector is unknown
Of course the selector is unknown since as part of the Target-Action design pattern you can specify whatever selector you want in order to get a call when something interesting happens.
What bugs me most about this warning is that it says there can be a potential memory leak. From my understanding ARC doesn't bend the memory management rules but instead simply automates the insertion of retain/release/autorelease messages at the right locations.
Another thing to note here: -performSelector: does have an id return value. ARC analyzes method signatures to figure out through application of naming conventions if the method returns a +1 retain count object or not. In this case ARC doesn't know if the selector is a -newFooBar factory or simply calling an unsuspicious worker method (which is almost always the case with Target-Action anyways). Actually ARC should have recognized that I don't expect a return value, and therefore forget about any potential +1 retain counted return value. Looking at it from that point of view I can see where ARC is coming from, but still there is too much uncertainty about what this really means in practice.
Does that now mean under ARC something can go wrong which would never happen without ARC? I don't see how this could produce a memory leak. Can someone give examples of situations in which this is dangerous to do, and how exactly a leak is created in that case?
I really googled the hell out of the internet but didn't find any site explaining why.
The problem with performSelector is that ARC doesn't know what the selector which will performed, does. Consider the following:
id anotherObject1 = [someObject performSelector:#selector(copy)];
id anotherObject2 = [someObject performSelector:#selector(giveMeAnotherNonRetainedObject)];
Now, how can ARC know that the first returns an object with a retain count of 1 but the second returns an object which is autoreleased? (I'm just defining a method called giveMeAnotherNonRetainedObject here which returns something autoreleased). If it didn't add in any releases then anotherObject1 would leak here.
Obviously in my example the selectors to be performed are actually known, but imagine that they were chosen at run time. ARC really could not do its job of putting in the right number of retains or releases here because it simply doesn't know what the selector is going to do. You're right that ARC is not bending any rules and it's just adding in the correct memory management calls for you, but that's precisely the thing it can't do here.
You're right that the fact you're ignoring the return value means that it's going to be OK, but in general ARC is just being picky and warning. But I guess that's why it's a warning and not an error.
Edit:
If you're really sure your code is ok, you could just hide the warning like so:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[specifiedReceiver performSelector:specifiedSelector];
#pragma clang diagnostic pop
The warning should read like this:
PerformSelector may cause a leak because its selector is unknown. ARC doesn't know if the returned id has a +1 retain count or not, and therefore can't properly manage the memory of the returned object.
Unfortunately, it's just the first sentence.
Now the solution:
If you receive a return value from a -performSelector method, you can't do anything about the warning in code, except ignoring it.
NSArray *linkedNodes = [startNode performSelector:nodesArrayAccessor];
Your best bet is this:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
NSArray *linkedNodes = [startNode performSelector:nodesArrayAccessor];
#pragma clang diagnostic pop
Same goes for the case in my initial question, where I completely ignore the return value. ARC should be intelligent enough to see that I don't care about the returned id, and therefore the anonymous selector is almost guaranteed not to be a factory, convenience constructor or whatsoever. Unfortunately ARC is not, so the same rule applies. Ignore the warning.
It can also be done for the whole project by setting the -Wno-arc-performSelector-leaks compiler flag under "Other Warning Flags" in project build settings.
Alternatively, you can surpress the warning on a per-file basis when you add that flag under Your Target > "Build Phases" > "Compile Sources" on the right-hand side next to the desired file.
All three solutions are very messy IMHO so I hope someone comes up with a better one.
As described above you get that warning because the compiler does not know where (or if) to put the retain/release of the performSelector: return value.
But note that if you use [someObject performSelector:#selector(selectorName)] it will not generate warnings (at least in Xcode 4.5 with llvm 4.1) because the exact selector is easy to be determined (you set it explicitly) and that's why compiler is able to put the retain/releases in the correct place.
That's why you will get warning only if you pass the selector using SEL pointer because in that case the compiler is unable to determine in all case what to do. So using the following
SEL s = nil;
if(condition1) SEL = #selector(sel1)
else SEL = #selector(sel2)
[self performSelector:s];
will generate warning. But refactoring it to be:
if(condition1) [self performSelector:#selector(sel1)]
else [self performSelector:#selector(sel2)]
will not generate any warnings
ARC is throwing the warning because it can't guarantee that the selector isn't creating an object it doesn't know about. You could theoretically receive something from that method that ARC can't handle:
id objectA = [someObject performSelector:#selector(createObjectA)];
Maybe someday it can, but right now it can't. (Note if it does know the object (it's not an id) it doesn't throw this warning).
If you're trying to simply execute a method without receiving an object back from it, I recommend using objc_msgSend. But you've gotta include in your class:
#include <objc/message.h>
objc_msgSend(someObject, action);
Background: CamelBones registers Perl classes with the Objective-C runtime.
To do this, every Perl method is registered with the same IMP
function; that function examines its self & _cmd arguments to find
which Perl method to call.
This has worked well enough for several years, for messages that were
dispatched with objc_msgSend. But now I want to add support for
returning floating-point and large struct types from Perl methods.
Floating-point isn't hard; I'll simply write another IMP that returns
double, to handle messages dispatched with objc_msgSend_fpret.
The question is what to do about objc_msgSend_stret. Writing a
separate IMP for every possible struct return type is impractical, for
two reasons: First, because even if I did so only for struct types
that are known at compile-time, that's an absurd number of functions.
And second, because we're talking about a framework that can be linked against any arbitrary Objective-C & Perl code, we don't know all the potential struct types when the framework is being compiled.
What I hope to do is write a single IMP that can handle any return
type that's dispatched via objc_msgSend_stret. Could I write it as
returning void, and taking a pointer argument to a return buffer, like
the old objc_msgSend_stret was declared? Even if that happened to
work for now, could I rely on it continuing to work in the future?
Thanks for any advice - I've been racking my brain on this one. :-)
Update:
Here's the advice I received from one of Apple's runtime engineers, on their objc-language mailing list:
You must write assembly code to handle
this case.
Your suggestion fails on some
architectures, where ABI for "function
returning void with a pointer to a
struct as the first argument" differs
from "function returning a struct".
(On i386, the struct address is popped
from the stack by the caller in one
case and by the callee in the other
case.) That's why the prototype for
objc_msgSend_stret was changed.
The assembly code would capture the
struct return address, smuggle it into
non-struct-return C function call
without disturbing the rest of the
parameters, and then do the right
ABI-specific cleanup on exit (ret $4
on i386). Alternatively, the assembly
code can capture all of the
parameters. The forwarding machinery
does something like this. That code
might be in open-source CoreFoundation
if you want to see what the techniques
look like.
I'll leave this question open, in case someone brainstorms a better idea, but with this coming directly from Apple's own "runtime wrangler," I figure it's probably as authoritative an answer as I'm likely to get. Time to dust off the x86 reference manuals and knock the rust off my assembler-fu, I guess...
It seems that the Apple engineer is right: the only to way to go is assembly code. Here are some usefull pointers to getting started:
From the Objective-C runtime code: The i386 and x86_64 hand-crafted messenger assmbly stubs for the various messaging methods.
An SO answer that provides an overview of the dispatching.
A in-depth review of the dispatching mecanism with a line-by-line analysis of the assembly code
Hope it helps.