clement@opus.cs.mcgill.ca (Clement Pellerin) (01/12/90)
In the SysRefMan chap. 3 p.27 there is an example on how to use the message free in class Object. The intent of free is to release the memory taken up by objects that you allocated with new but you don't need anymore. The example is [self free]. Note that self will be deallocated by the time this message returns. The object class of self will not be deallocated and hence the method will still be available. The instance variables of self will be gone. Should an object that does not exist anymore be allowed to continue executing a method if it does not access its variables nor sends a message to itself? What does the objective C ref manual say about this? I tried the following program and the variables are kept after [self free] but you can't send a message to self. I would prefer if I would get a run-time error by accessing the variables. let me propose a different example: id anObject; anObject = [AClass new]; // use anObject until you don't need it [anObject free]; // continue execution without anObject Is it worth contacting NeXT? --------------------<snip>------------------------<snip>----------------------- // put me in file selffree.m // compile me with cc -ObjC -I/usr/include/objc selffree.m -lNeXT_s -lsys_s // it took me 30mins to find that command, is there a better way? #import <Object.h> @interface Suicide:Object { int x; } - setx: (int)val; - die; - sayhi: (int)cnt; @end @implementation Suicide:Object; - setx: (int)val { x = val; } - die { [self free]; printf("I'm dead but I remember the value of x = %d\n", x); [self sayhi: 2]; } - sayhi: (int)cnt { printf("I'm alive %d\n", cnt); } @end main() { Suicide *suicidal; suicidal = [Suicide new]; [suicidal setx: 111]; [suicidal sayhi: 1]; [suicidal die]; [suicidal sayhi: 3]; } --------------------<snip>------------------------<snip>----------------------- -- news <clement
jacob@gore.com (Jacob Gore) (01/13/90)
/ comp.sys.next / clement@opus.cs.mcgill.ca (Clement Pellerin) / Jan 11, 1990 / > In the SysRefMan chap. 3 p.27 > there is an example on how to use the message free in class Object. [...] > The example is [self free]. This is indeed a bad example. It's technically correct, but it belongs in something like "Objective-C Traps and Pitfalls", not as an example for the typical use of -free. > Note that self will be deallocated by the time this message returns. The > object class of self will not be deallocated and hence the method will > still be available. The instance variables of self will be gone. I don't follow this reasoning. Whether or not the methods of the former self are still callable is at best implementation-dependent. For example, if methods are reached through the 'isa' instance variable (a pointer to the class struct), and that variable is not available anymore, neither are the methods. You may get "lucky" if all pointers just happen to be intact in memory, or because the method is cached, etc. In any case, trying to access instance variables or instance methods of a freed objects is a bad idea. > Should > an object that does not exist anymore be allowed to continue executing a > method if it does not access its variables nor sends a message to itself? Yes, since it may not access its variables or send messages to itself for the rest of the execution of the method. Besides, 'self' is assignable. One may want to do something like this: - finishUnarchiving { if ([self isInconsistent]) { [self free]; self = [SelfsClass new]; [self setSomeInstanceVariables]; } return self; } > What does the objective C ref manual say about this? Don't know, don't have one. > I tried the following program and the variables are kept after [self free] > but you can't send a message to self. I think that's a fluke. > I would prefer if I would get a run-time error by accessing the variables. I agree. > let me propose a different example: > > id anObject; > > anObject = [AClass new]; > // use anObject until you don't need it > [anObject free]; > // continue execution without anObject Yes, except I'd use "AClass *anObject" instead of "id anObject". Now that we finaly have compile-time object typing in Objective-C, let's encourage people to take advantage of it. I would also provide an example on how to write the -free method for an object: #import "Something.h" @interface Example : Object { char *aString; Something *aSomething; } + new; - free; @end #import <stdlib.h> @implementation Example + new { self = [super new]; aString = malloc(100); aSomething = [Something new]; return self; } - free { if (aString) free(aString); // May still fail if aString is // neither NULL nor points to a // malloc'ed chunk. [aSomething free]; // If aSomething is nil, any // message sent to it is a no-op. return [super free]; // The convention is for all -free // methods to return nil. } @end > Is it worth contacting NeXT? Definitely about the manual, and probably about having run-time errors generated in the situation you presented. Are you going to? Jacob -- Jacob Gore Jacob@Gore.Com boulder!gore!jacob
eps@toaster.SFSU.EDU (Eric P. Scott) (01/13/90)
In article <130056@gore.com> jacob@gore.com (Jacob Gore) writes: >This is indeed a bad example. It's technically correct, but it belongs in >something like "Objective-C Traps and Pitfalls", not as an example for the >typical use of -free. ok, but ... >Besides, 'self' is assignable. Bingo. (This may be more useful in class methods than instance methods.) Note: If you're using the Application Kit, Application's delayedFree: may be just what you're looking for. -=EPS=-
dennisg@kgw2.uucp.WEC.COM (Dennis Glatting) (01/13/90)
In article <1842@opus.cs.mcgill.ca>, clement@opus.cs.mcgill.ca (Clement Pellerin) writes: > > The example is [self free]. Note that self will be deallocated by > the time this message returns. The object class of self will not be deallocated hmm. remember that self is just a pointer to a memory location. just because one malloc() something doesn't imply it can't be accessed after free(). the results cannot be predictable. therefore, yes, i beleive you can access those instance variables. self, a simple pointer, isn't erased. uou simply forget about it. i would think that if you subclass had a free method then you might get a infinite loop with [ obj free ]. don't ya tink? > Is it worth contacting NeXT? > sure, just email bug_next@next.com. -- dennisg@kgw2.bwi.WEC.COM | Dennis P. Glatting ..!uunet!tron!kgw2!dennisg | <<This section isn't available on-line.>>
ed@DTG.COM (Edward Jung) (01/14/90)
In article <1842@opus.cs.mcgill.ca>, clement@opus (Clement Pellerin) writes: [a bunch of stuff] This is a rather long message in reply to Clement Pellerin's question about [self free] in Objective-C. SOME BACKGROUND Pure object oriented languages do not allow direct access to instance variables; all access is mediated by messages. In Smalltalk and CLOS (Common Lisp Object System), for example, you do not access instance variables directly, but rather through an access method. Objective-C, being a hybrid language anyhow, allows instances to access their own instance variables directly, and the instance variables of other instances that have been declared using the @public keyword or via structs and the @defs keyword. One side-effect of direct access to instances is that instance variables must be fixed in size throughout the duration of an execution of a program. You can add methods to a class definition at run-time, but you cannot change the size or number of a class' instance variables. (We are working on a system that will allow this via incremental run-time relink). HOW THE COMPILER MAKES AN OBJECT An object (class instance) is allocated using the equivalent of malloc(). This is performed by Object's new method. The symmetric free() is performed by Object's free method. Since all allocation and freeing is performed via the inheritance chain (calls to super), all objects end up allocated and freed in this manner. Classes are allocated at load time, along with information about the methods, method names, argument types, selectors, instance variables, instance variable names, and instance variable types. All this information is available at run-time and is embedded in the OBJC segment in a Mach-O file. Note also that there is a provision for class variables, but the Objective-C syntax does not handle this (yet?). HOW THE COMPILER HANDLES INSTANCE VARIABLE ACCESS Every reference to an object's instance variables is translated to an offset pointer lookup to self. self is a parameter that is secretly passed into every method (as is the selector for that method); it is used implicitly to reference an object's instance variables. Assume the following method in the class MyObject, and anInstanceVariable is an instance variable of MyObject: - setAnInstanceVariable:(int)toThisInt { anInstanceVariable = toThisInt; return self; } The code produced by the compiler actually looks something like this (in ANSI C syntax): id setAnInstanceVariable(id self, SEL _cmd, int toThisInt) { self->anInstanceVariable = toThisInt; return self; } So methods are converted into ordinary functions. Of course the real code is output in object code on the NeXT, and the function name is bound to a rather strange name, but the basic idea is the same. HOW THE COMPILER HANDLES MESSAGE SENDS Message sends, on the other hand, are all vectored through one of two message dispatchers: objc_msgSend() and objc_msgSendSuper() (or equivalent). These dispatchers are given the value of the receiver of a message, and the message selector, perform a lookup to find the function (the converted method, as in the above example) associated with the receiver and selector, and jump to that function. In this process, the dispatcher examines the "isa" link of the receiver. If it has an invalid value, the dispatcher gives a run-time error. WHEN YOU FREE AN OBJECT USING [anObject free], THE isa LINK IS GIVEN AN INVALID VALUE, so the error is generated. This is to assist in trapping the occasional bug where you send a message to a freed object. Since access to instance variables is performed through a pointer offset, this mechanism is not sensitive to the value of the isa link. As this is a very fast means of accessing the instance data, the overhead of adding a check of the isa link to every such call would be significant (since method lookup is a rather more complex process, the lookup is relatively less expensive). GETTING BACK TO THE QUESTION So the example given by NeXT is correct, though perhaps ambiguous. [self free] is the correct way to release the memory associated with an object. [self free] is semantically equivalent to: char * aPtr; ... aPtr = malloc(256); ... free(aPtr); /* aPtr is now freed */ In the above example, you could access aPtr after freeing it, but that's not the "right" thing to do. You can still exist in the scope of the method that called [self free], because freeing an object does not do anything to the method code; it does, however, invalidate certain variables (again, just like the malloc/free example above). This is why the safest way to write a free method in a class is as follows: - free { free(aPtr); /* free all the other junk */ return [super free]; } WHAT IS WRONG WITH THE SUICIDE EXAMPLE? You should not do anything with an object after it has been freed. Just like a dynamically allocated pointer. Should an object that does not exist anymore be allowed to continue executing a method if it does not access its variables nor sends a message to itself? Yes. Its storage has been freed, but the methods are independent, and might be thought of as owned by the class, which still exists. The definition of an instance of a class is essentially a copy of the data formed from the template defined in the class; the methods are shared by all the instances, and thus are independent from the existance of the instances. I would prefer if I would get a run-time error by accessing the variables. This is a problem stemming from the semantics of dynamically allocated memory without garbage collection. Is it worth contacting NeXT? I don't think so. Perhaps the manual could be made clearer, but the semantics of Objective-C are correct for its model. Perhaps the thing to wish/ask for is garbage collection, if memory management is a headache. In C, dynamically allocated objects (instances, pointers or otherwise) are the programmers' responsibility to track. Note that you can do some interesting things with the new and free semantics, such as implementing an object cache to minimize heap fragmentation from repeated allocations of object instances and/or the instance variables that are dynamically allocated pointers: #define FOP_SIZE (32) static MyClass free_object_pool[FOP_SIZE]; static int num_in_fop = 0; + new { if (num_in_fop > 0) { num_in_fop--; self = free_object_pool[num_in_fop]; anInt = 100; } else { self = [super new]; anInt = 100; aPtr = malloc(10000); } return self; } - free { if (num_in_fop < FOP_SIZE) { free_object_pool[num_in_fop] = self; num_in_fop++; return nil; } else { free(aPtr); return [super free]; } } Of course in this example you may be able to continue to send messages to instances that have been freed, but you should never do that anyhow. There are a host of other optimizations that can be done with Objective-C, including determining the static address of a method to avoid message passing overhead in inner loops, etc. Further detail about this and other Objective-C matters might be better addressed via email to conserve news bandwidth. -- Edward Jung The Deep Thought Group, L.P. BIX: ejung 3400 Swede Hill Road NeXT or UNIX mail Clinton, WA. 98236 UUCP: uunet!dtgcube!ed Internet: ed@dtg.com