I wanted to know , How exactly does an Objective C object gets created. I have been reading different blog posts and apple docs but I could only find incomplete information here and there about ivar and objc_class structures ad various other runtime methods and structures.
But I still did not get, What happens when we call alloc on a Class and how are superclass data members added to the structure ?
If possible, can any one Explain this to me or point me to the source code of these methods that actually allocate memory ?
When alloc is called, it (as any other message send) first gets transformed (by the compiler) into one of the objc_msgSend* functions. This function will get the class structure pointer as its first argument, and #selector(alloc) as its second.
Then, objc_msgSend looks up the corresponding method implementation of +[class alloc], which is, in general, not overridden (custom initialization is conceptually done in -initWith...), so it will generally be +[NSObject alloc]. It is likely that alloc simply calls +[NSObject allocWithZone:]; that function's implementation might do the following steps:
1) It finds the class' istance size (probably via class_getInstanceSize())
2) It allocates memory, most likely using the class_createInstance() function. This function clears the allocated memory to zeroes (that's why, as the specs say, all your ivars are explicitly initialized to 0 on startup), then sets the newliy created object's isa pointer to the class structure itself.
3) The allocWithZone: methods returns the fresh object pointer to alloc
4) alloc returns the object pointer to the sender, most likely it will run into [Class initWith...:].
Hope this helps. Also, apart from the Obj-C runtime docs, don't forget to check the GNUstep NSObject implementations. That's a logic and possible way how the GNU people implemented it and how Apple might have implemented it.
Check out http://www.mikeash.com/pyblog/friday-qa-2009-03-13-intro-to-the-objective-c-runtime.html
Related
I've read here recently that an objective-c object is stored on the heap as a struct. The struct contains the objects iVars, inherited iVars, and the isa pointer.
I'm trying to figure out when I send a message to this object, how does the run-time figure out the code to run?
I know there is a class object for each class. Is this also stored on the heap?
I think the way it works is that the run-time gets the isa pointer from the struct, uses this to call the message on the class object. Is this correct?
In short, every Objective-C instance has a pointer to its class. The class contains an inventory of metadata that includes all the methods that the class implements. When a message is sent to an object -- when a method is called -- the runtime uses the pointer to the class to lookup the method by name and call it, if it can be found. If it isn't found, the runtime looks to the superclass (which is a part of each class's metadata) on up the inheritance chain to NSObject. If the method ultimately can't be found, the runtime goes through a series of last ditch efforts to see if their is an alternative handler and eventually raises an exception, if not.
If you want more detail than that, I wrote up a multipart tour of exactly how Objective-C method dispatch works. It is slightly out of date -- doesn't deal with ARC, tagged pointers or blocks-as-IMP -- but still fully applicable.
Yes, classes are stored in the heap, but generally not in malloc()d memory. Classes are generally loaded as read-only, shared, memory. That is, there will be only one copy of the NSString class in memory for all applications running on the system. You can dynamically create classes on the fly and these will be in the regular heap, but it is atypical.
I am a experienced developer that is new to iOS developement (on iPhone in particular). A project I am working on is using Automatic Reference Counting (ARC).
I was doing some research on ARC and came across this document: http://clang.llvm.org/docs/AutomaticReferenceCounting.html and in a section titled: "Retained return values" it states that an attribute can be used to indicate that the caller expects to take ownership of a +1 retain count. It also goes on to state that ARC will automatically add the attribute to methods if it detects it is in particular method families (it specifically names: alloc, copy, init, mutableCopy, and new)
From further reading it seems that method families are simply method naming conventions. My understanding is that if the method name starts with a method family then it is in that method family. So for example
+(id) init
+(id) initWithName:(NSString*)name
are both part of the init method family.
My question is: Is there a formal list of defined Method Families for iOS development and if so, what are they / where might I find it?
below is the section llvm.org I mentioned above:
Section 3.2.2: Retained return values states:
A function or method which returns a retainable object pointer type
may be marked as returning a retained value, signifying that the
caller expects to take ownership of a +1 retain count. This is done by
adding the ns_returns_retained attribute to the function or method
declaration, like so:
id foo(void) __attribute((ns_returns_retained));
- (id) foo __attribute((ns_returns_retained)); This attribute is part of the type of the function or method.
When returning from such a function or method, ARC retains the value
at the point of evaluation of the return statement, before leaving all
local scopes.
When receiving a return result from such a function or method, ARC
releases the value at the end of the full-expression it is contained
within, subject to the usual optimizations for local values.
Rationale: this formalizes direct transfers of ownership from a callee
to a caller. The most common scenario this models is the retained
return from init, alloc, new, and copy methods, but there are other
cases in the frameworks. After optimization there are typically no
extra retains and releases required.
Methods in the alloc, copy, init, mutableCopy, and new families are
implicitly marked attribute((ns_returns_retained)). This may be
suppressed by explicitly marking the method
attribute((ns_returns_not_retained)).
It is undefined behavior if the method to which an Objective-C message
send statically resolves has different retain semantics on its result
from the method it dynamically resolves to. It is undefined behavior
if a block or function call is made through a static type with
different retain semantics on its result from the implementation of
the called block or function.
Rationale: Mismatches with returned results will cause over-retains or
over-releases, depending on the direction. Again, the rule about
function calls is really just an application of the existing C/C++
rule about calling functions through an incompatible function type.
Section 5 of the same document is titled "Method Families". It lists all the currently defined families, which are the ones you identified above; alloc, new, copy, mutableCopy, and init. It also lists the criteria for being part of that family. Mostly, it's just based on the method name, but it also depends on the return type. For example, a member of the copy family must return an object; a copy method that has a void return type will not be considered part of the copy method family.
I don't know that I've seen a formal list of method families, but your analysis is basically correct. I believe the only method naming conventions that have compiler-enforced semantics are those mentioned in your post, namely alloc, init, copy (and mutableCopy), and new. Even before/without ARC, the clang static analyzer included in Xcode uses those naming conventions to find memory management problems, and they're also the basis of the longstanding memory management rules for Objective-C programmers prior to ARC.
Namely, if you create an object using a method that begins with init, copy, mutableCopy or new, you "own" that object and are responsible for releasing it later. Objects created or returned by methods with any other name, are not owned by you, the caller, and if you want to keep a reference to them, you must retain them. Every retain you make must be balanced by a later release, when you're done with the object reference. Finally, calling autorelease on an object puts it in the innermost autorelease pool. The pool is responsible for releasing the object later, where later is sometime after the current scope. So, release and autorelease are both valid ways of relinquishing your retain on an object.
Now, the rules I've set forth shouldn't (and can't) be followed by you, the programmer, under ARC. However, ARC is essentially a system whereby the compiler with help from the static analyzer knows these rules and inserts the necessary memory management calls for you at compile time. So, if you're looking to develop an understanding of what ARC is doing behind-the-scenes, understanding these rules is a good start.
This turned out a bit longwinded, but the point is that the methods you've named are the only ones I know of that have this enforced naming convention in Objective-C, and it stems from the memory management rules set forth above. There are other naming conventions in Objective-C, to be sure, but they're standard style conventions, not something that's enforced anywhere.
Look at official Apple Developer documentation about Memory Management Rules. Seems, your list is complete: “alloc”, “new”, “copy”, or “mutableCopy” (only 4 keywords).
I would include the convenience constructors provided by some Cocoa classes:
- +stringWith* // Various ways to make NSString objects
- +arrayWith*, +dictionaryWith*, etc. // Make collections
- +dateWith* // Make NSDate objects
- etc. // Many, many others
They all return a new, autoreleased instance of the class they are sent to - except for some special cases, see for instance #Peter Hosey's comment.
I don't know if there are any formal rules, but the pattern is that the constructor name is composed of the class name without the NS part (and without the Mutable part, too, for mutable classes) followed by With<Parameter Type>: and one or more parameters. The name begins with a lower case letter (except the usual suspects, like URLWithString:.)
For instance, the following line provides an autoreleased NSArray instance with a single element:
[NSArray arrayWithObject: #"Test"]
I don't know if there are any special rules in the compiler to recognize this type of constructor.
First off, I'm a Objective-C newbie. :)
I've learned that anything that starts with alloc, new, and copy, gives the caller ownership of the returned object. Does this also apply to class methods? I'm guessing it does, and a recent crash in one of my unit tests seems to confirm it. Apple's Advanced Memory Management Programming Guide doesn't say anything whether there's a difference between class and instance methods.
Update
What I mean that it also applies to class methods is really the "inverse". For instance, NSDecimalNumber has a class method called +decimalNumberWithDecimal:. It seems to return an auto released object (if I release it explicitly, a crash occurs shortly after that). In hindsight, the answer to my question is obvious, as Apple's guide refers to new and alloc as ownership-giving methods, and they're all class methods. Sorry for taking up your valuable time. :)
Also alloc and release. init does not indicate ownership, you are likely mixing that up with alloc. You can memorise it easily with the mnemonic NARC.
If you are naming any class methods init, copy or retain, you should stop that. Those are methods that only make sense in the context of instances. alloc and new are class methods and should only be used in that context. Don't name instance methods alloc or new.
The reason why the guide doesn't say that it applies to both instance methods and class methods is that the methods in question are clearly a mixture of both, so it's obviously the case.
Yes this applies to class methods since alloc and new are class methods which return ownership to the caller. The prefix of copy or mutableCopy should be used for instance methods returning ownership.
Edit For The Update:
You are correct a method like +decimalNumberWithDecimal: is expected to return an autoreleased object, therefore there is no reason to release it. If however they decided to name the method +newNumberWithDecimal: then you would have ownership of the returned object and need to release it. Clang static analyzer will actually complain if you prefix a method with new and return an autoreleased object.
Actually, this is almost correct. alloc, new, and copy give you ownership of the returned object. These are class methods. Other class methods should return an autoreleased object. Instance methods should also return an autoreleased object.
init does not effect ownership and should be use in conjunction with alloc as follows.
[[SomeCoolClass alloc] init]
new is usually the same thing as the above and is sometimes described as "almost deprecated" because it is a throwback to the NeXT days when the allocation and initialization were done in the same step and could not be plot apart as we do today with alloc and init.
Release does not effect ownership, but should only be used on object you already own. Otherwise a crash is likely to occur.
Retain also does not affect ownership, but should only be used on an object you already own. Otherwise the object may not be deallocated when it should be. The result could be a crash, but it can also be very very strange behavior that is difficult to troubleshoot because messages may be sent to the original object that was supposed to have been deallocated instead of a new object pointed to at the same address.
As i was reading through the book on Objective-C, i came across an example that initialized a class as follows:
ClassName *p = [[ClassName alloc] init];
While it makes sense that first we need to allocate memory to store data ClassName has before initializing, the following works just as well:
ClassName *p = [ClassName alloc];
Is init always needed?
In theory, it's not technically required. That's because NSObject's init method is effectively just return self;. However, in practice, it's absolutely essential. Objects perform internal setup inside the init method - creating internal state, allocating private members, and generally getting ready for action. The init method may not even return the same object as you allocated.
Think of it in two phases: alloc allocates memory, but that's it - it's analogous to Java's new. init configures the state of the memory so that the object can perform it's tasks - analogous to Java calling the constructor. Don't leave it out!
Good question. And you're right. Strictly speacking "init" is not required.
"alloc" does three important things to create an object:
- allocate enough memory to hold all instance variables
- initialize the "isa" instance variable
- all other instances are set to 0
Consider that the "root" Cocoa object, NSObject, simply returns "self" in its init method.
But, if you want to be a good Obj-C citizen, you must use "init". It is part of the "contract" between you, the developer, and the environment.
You should always call one of the initializer methods especially when the class isn't your own. The pointer returned from init isn't necessarily the same as returned by alloc.
Read the documentation:
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050-init
Im getting fairly confused as the book im reading is delving into the NSNumber class and talks about all the different methods you can call on it. I have a couple questions:
1.) Do you not have to call a typical alloc or init on foundation classes?
2.)in what cases would you use, say, numberWithChar: as opposed to initWithChar (i think this is the part that is messing me up the most, not really sure im groking this concept on the level i need to be, if you folks could break it down for me I think it would really help me get over this humper-roo.
Thanks,
Nick
Class/Instance Analogies
Classes are like blueprints for a type house. Instances are like actual houses. So you can only have one blueprint for a single type of house, but you can have multiple actual houses of the same type. Also, you can have multiple blueprints, and each blueprint describes a different type of house.
Another analogy you can use is that classes are like cookie cutters, and instances are like cookies made from a cookie cutter.
How It Applies To Objective-C
There is one "class object" for every class in your code. To refer to the class object, you just use the class name. alloc is a class method that allocates a new instance like so:
MyWidget* w = [MyWidget alloc];
However, alloc doesn't initialize the class, so none of the member variables will be set up. init is an instance method that will initialize a newly allocated instance. So to allocate and initialize a new instance, you do this:
MyWidget* w = [[MyWidget alloc] init];
Which is equivalent to this:
MyWidget* w = [MyWidget alloc]; //alloc is being called on the class
w = [w init]; //init is being called on the instance
Another common type of class method is a factory method like numberWithChar:. This is basically what numberWithChar: does:
+(NSNumber*) numberWithChar:(char)c;
{
return [[[NSNumber alloc] initWithChar:c] autorelease];
}
The only real difference is that numberWithChar: returns an autoreleased object.
All objects must be allocated and initialized. That includes foundation classes.
1) alloc and init need to be called virtually always. numberWithChar is a convenience method, which means it calls alloc, init, and autorelease for you and returns the autoreleased instance.
2) Since numberWithChar returns an autoreleased object, that means unless you retain it (or pass it to something like an NSArray which will retain it), it'll be destroyed shortly. initWithChar returns a retain-ed object, which means you have to release it when you're done with it.
I found when I was starting out that it was helpful to use init-alloc as a rule, instead of the convenience methods, because it made me pay close attention to my memory management.
The difference between class and instance methods is addressed from a number of angles in the answers to this question What is the difference between class and instance methods?
EDIT:
To be honest, the analogy I use when I call a class method on, say NSString, is praying to the god of NSStrings to bestow upon me a magnificent new NSString. Notice that class methods are almost 100% used for creation. e.g. alloc is a class method, stringWithFormat is a class method, and so on.
Yes, it's ridiculous, I know.
Ok, first thing: In Objective-C, you don't call a method, you send a message to an object. The runtime looks up the methods and calls them.
It might help you to think of a class as a factory. In fact, years ago, we used to refer to class methods as factory methods.