On Tue, 12 Feb 2002, Markus Gerwinski wrote:
Hi folks,
Frank Heckenbach wrote (in reply to da Silva, Joe):
Obviously, you need pointers to represent such structures. Creating them is not a problem, but how to clean up properly? You can traverse all pointers in the object and clean up the objects they point to recursively. But that's wrong because those objects might be referred to from elsewhere. Also, with cyclic references, you'd run into an endless loop.
This is not to say it's impossible (I mentioned reference counting, and there are ways to avoid the endless loop), but is this much simpler than GC? In fact, if you consider the whole memory as a large tree(*), the resulting algorithm wouldn't look much differently from a GC algorithm ...
If this inter-dependence with GCC also means that garbage collection is a requirement, then "so be it" ...
Practically, it does. But if you know a better solution, even if only in theory, I'd be interested, just for curiosity.
I'm currently working on a framework including an object type named "tReferenceManager". It is intended to exactly solve this problem, at least for synchronization of collections (lists, hashtables etc.): For every pointer, you can subscribe _one_ collection it is stored in, plus an arbitrary number of reference collections. When the pointer is removed from the store collection, it is automatically disposed, and all of the references are removed from the reference collections.
I hope to complete the respective unit of this framework within a few weeks. If anyone thinks he/she can use it, I'll announce it after this unit is ready. (Frank: The framework contains also the exception handling unit we already talked about.)
Personally, I _really_ dislike garbage collection since I had to deal with it in an optimization problem in Java. ;-/ IMO, providing a language with GC is just a way to encourage programmers to give up control. An alternative feature I'd like to see in a language would be to split pointers into two separate data types: "store" pointers and "reference" pointers. Allocating and deallocating may only be done on a store pointer; setting a pointer to an already existing address may only be done with a reference pointer. When disposing of a store pointer, itself and all of its references are automatically set to nil, so you can always check whether the pointer is pointing to valid data. (It's the same principle I'm using in my tReferenceManager, and up to now I didn't find any disadvantages in it. Except that you are forced to think before you code.;-)
Perhaps I'm missing something. I thought the purpose of GC was to maintain a list of free memory. Thus GC doesn't care how you access a block, it cares only if it is free or not. A simple GC would recognize adjacent free blocks and combine them into a larger single block. A more complex scheme could move already allocated blocks to make a large free block when one is needed. This last might be implemented by adding a transparent level of indirection. Programmer thinks his pointer p is pointing to something when in reality it is pointing to an internal pointer pointing to the something. Thus when the block gets moved only one pointer needs to be changed.
Along with GC you have the problem of do you allocate first fit or best fit? Each has its pros and cons.
And just how is gcc doing GC and friends? (was lazy and didn't do much digging thru the code.)
Just some thoughts, Russ