> I believe the main difficulty comes from heading into uncharted waters. For > example, once you've decided to make garbage collection optional, what does > the following line of code mean? > > delete x;
If the above code is compiled to Parrot, it probably equivalent to x->~Destructor(); i.e., the destructor is called, but the memory is left to GC, which most likely handle free at a later time. > Or, for example, are the side effects of the following two functions > different? > > void f1() > { > // On the stack > MyClass o; > } > > void f2() > { > // On the heap > MyClass o = new MyClass(); > } > > If garbage collection is not 100% deterministic, these two functions could > produce very different results because we do not know when or if the > destructor for MyClass will execute in the case of f2(). This is exactly the same case for C++. When you compile f2 with gcc, how can you tell when the destructor is called. Even the following code does not work. void f3() { MyClass o = new MyClass(); ... delete o; } If there is an exception happens within (...), the destructor will not be called. > If garbage collection is > not 100% deterministic (and Mark and Sweep is not), we need extra language > features, such as Java's "finally" block, to ensure things can be cleaned > up, and extra training to ensure programmers are smart enough to know how > to use "finally" blocks correctly. That is exactly the case for C++. In your above code f1(), the C++ compiler already (behind the scene) inserts finally block for "o" destructor. That is why the destructor of stack allocated objects is called even when exception happens. The only difference is that the memory deallocation is dis-associated with object destruction. Summary: the object destruction with GC is as deterministic as C++ heap allocated object, i.e. you have to call "delete x" (in C++), x.close() (in Java), x.dispose (in C#), otherwise is 0% deterministic, period. Hong