alistair@minster.york.ac.uk (02/24/89)
Can anyone out there explain how Object Pascal objects are allocated in memory, and the relationship to segementation? I have a program which sometimes bombs due, I suspect to memory problems. I should say that I am NOT using MacApp. An object is a handle, right. So when if write: type Tthing = object(Tobject) i : integer; procedure p; ... end; {$S seg1} procedure Tthing.p; ... {$S seg2} var thing : Tthing; begin new(thing) New allocates some memory on the heap and thing is set as an indirect pointer to it. What goes in that bit of memory: the code for Tthing (i.e. for Tthing.p) and/or space for the instance variable i? What if I call new for another Tthing object? Surely I don't need another copy of the code for Tthing.p, but do I get one anyway? What does dispose(thing) do? And then... I have had to segment my program because the compiler began to complain about segments >32K, but what does that mean in the context of objects? Can I unload a segment I have finished with by something like UnloadSeg(@thing.p) - and what would it mean if I did? How would that work in relation to a dispose(thing)? I hope someone out there is able and willing to help. I did try getting the answers from the Apple Developers' Group - the British version of APDA - and they knew no more than me, and couldn't be bothered finding out. As far as I'm concerned they are a waste of time and I don't care who knows it. (These are - of course - NOT necessarily the views of my employers, blah blah blah)
siegel@endor.harvard.edu (Rich Siegel) (03/01/89)
In article <604330910.18716@minster.york.ac.uk> alistair@minster.york.ac.uk writes: >Can anyone out there explain how Object Pascal objects are allocated in memory, In Lightspeed Pascal (and probably in MPW Pascal as well), an OBJECT type is allocated as a handle in the heap; the first word of the handle is an A5-relative offset to the class info proc, and the rest of the space, I believe, is for the instance variables. It's important that the DECLARATION for an object type be in the main segment (or in some other segment that won't be unloaded or moved around), but the implementation of a method can be in any segment, as long as you don't do anything like unload your caller's segment. --Rich Rich Siegel Staff Software Developer THINK Technologies Division, Symantec Corp. Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel Phone: (617) 275-4800 x305
rick@Jessica.stanford.edu (Rick Wong) (03/01/89)
In article <604330910.18716@minster.york.ac.uk> alistair@minster.york.ac.uk writes: >Can anyone out there explain how Object Pascal objects are allocated >in memory, and the relationship to segementation? > You've come to the right place! > >New allocates some memory on the heap and thing is set as an indirect >pointer to it. What goes in that bit of memory: the code for Tthing >(i.e. for Tthing.p) and/or space for the instance variable i? What if >I call new for another Tthing object? Surely I don't need another copy >of the code for Tthing.p, but do I get one anyway? What does >dispose(thing) do? > Only the space for the object's instance variables are allocated. The code is loaded in from your application's CODE resources when needed. There is at most one copy of the code in memory at any time, regardless of the number of instances of Tthing. Dispose(thing) should dispose the object by calling DisposHandle on the object handle. Rather than call dispose, you should use the standard TObject interface and call thing.Free, which will give your object a chance to clean up after itself and free any other things it may have allocated. > >And then... I have had to segment my program because the compiler began >to complain about segments >32K, but what does that mean in the context >of objects? Can I unload a segment I have finished with by something >like UnloadSeg(@thing.p) - and what would it mean if I did? How would >that work in relation to a dispose(thing)? > UnloadSeg and dispose are completely unrelated. Freeing an object only releases the memory occupied by its instance variables (i.e., its handle). The code will remain in memory until you call UnloadSeg on it. Calling UnloadSeg in Object Pascal may be tricky. I've never tried it because MacApp does it for me automatically. The call you give for it (UnloadSeg(@thing.p)) doesn't make sense -- you have to pass it the address of a procedure or function. This is probably where you're running into trouble, since I suspect you may be inadvertently passing the address of some sort of method dispatching table. To be safe, you should declare a dummy normal Pascal procedure in each of your unloadable segments and use that to unload them, e.g.: {$S Segment1} procedure StupidDummyRoutineForUnloadingSegment1; begin end; . . . and in your main event loop: UnloadSeg(@StupidDummyRoutineForUnloadingSegment1); Hope this was helpful. Rick "No, it's Hair Pie" Wong Courseware Authoring Tools Project, Stanford University rick@jessica.stanford.edu
ech@pegasus.ATT.COM (Edward C Horvath) (03/01/89)
From article <532@Portia.Stanford.EDU>, by rick@Jessica.stanford.edu (Rick Wong):
> Calling UnloadSeg in Object Pascal may be tricky...
Calling UnloadSeg is downright dangerous until you have a better understanding
of how to segment your code. Read the MPW Linker description, paying
particular attention to the "new segment" commands. Read the analogous parts
of your pascal manual. Repeat as needed. Now organize your program into
groups of related functions until all the groups are under 32K in size.
Finally, VERY CAREFULLY introduce UnloadSeg calls so that nobody ever tries
to UnloadSeg a segment FROM WHICH IT MIGHT BE CALLED.
Scott Knaster recommends a simpler approach, namely at one place, at the top
of your event loop, call UnloadSeg for every segment except CODE 1. Oh, yeah:
make sure the event loop is in CODE 1! While this approach is nowhere near
optimal, it's simple and hard to screw up. Doing a proper job requires that
you truly understand the flow of your program. (Is there anything like
'cflow' in MPW?)
If this sounds like a royal pain in the back of your lap, you're absolutely
right. If you're writing a commercial application with rigid memory
constraints you will have to do it anyway. Or hope that MacApp does it
right for you, but MacApp is not the Philosopher's Stone: it can only deal
properly with what it understands.
But if you're doing a something less life-and-death, you can just break the
code into segments wherever you please to get 'em all under 32K. If you
like, mark all the CODE resources PreLoad with ResEdit, or use the Knaster
hack. Repeat, I do NOT recommend this for anything which is going to ever
see the light of day, and for ghod's sake don't put MY name on it, but when
it doesn't matter why bother?
=Ned Horvath=