GC BUG: Referenced object destroyed before released
Graham St Jack
grahams at acres.com.au
Sun Mar 16 15:28:04 PDT 2008
On Sun, 16 Mar 2008 16:45:14 +0300, Koroskin Denis wrote:
> Hello, community!
> Consider the following code:
>
> // For those who prefer alternative reality ;) version(Tango) extern(C)
> void printf(char[] s, ...);
>
> class Resource
> {
> private char[] data;
> private bool released;
>
> this()
> {
> this.data = null;
> this.released = false;
> }
>
> ~this()
> {
> printf("Resource destroyed\n");
> }
>
> void release()
> {
> released = true;
> }
> }
>
> class Owner
> {
> private Resource res;
>
> this(Resource res) {
> this.res = res;
> }
>
> ~this()
> {
> res.release();
> printf("Owner destroyed\n");
> }
> }
>
> int main()
> {
> Resource res = new Resource();
> Owner owner = new Owner(res);
>
> printf("Main exit\n");
> return 0;
> }
>
> In this code we don't explicitly destroy anything, so GC chooses the
> order of object destruction. And it chooses wrong.
>
> "Phobos hack" shows the following stack trace upon exit:
>
> Main exit
> Resource destroyed
> Unhandled win32 exception!
> Error: Access Violation (object.Exception) backtrace:
> 00402087 void crash.Owner._dtor() (+f) crash.d:35 0040262a
> _d_callfinalizer (+46)
> 004025dd void std.gc.new_finalizer(void*, bool) (+9) 004066c3 void
> gcx.GC.fullCollectNoStack() (+3b) 0040226f gc_term (+b)
> 00415b6d mainCRTStartup (+a9)
> 7c816d4f ???
>
> or without it:
>
> Main exit
> Resource destroyed
> Error: Access Violation
>
> or with Tango:
>
> object.Exception: Access Violation
> tango.core.Exception.FinalizeException: An exception was thrown while
> finalizing an instance of class crash.Resource
>
> object.Exception: Access Violation
>
> Was there any bug report filled on this bug? It's very annoying, since
> it makes your program not reliable in runtime. At least, if it was a
> compilation bug, and I managed to bypass it, I would be assured, that
> the resulted program whould behave predictable. Yet, it is not...
I agree that this is a problem. Who cares if the two objects in question
aren't referenced and more - their destructors should be called in the
right order if it is possible to do so.
I guess the work-around (and maybe permanent) is to not reference any
garbage-collected objects in your destructors.
More information about the Digitalmars-d
mailing list