GC can collect object allocated in function, despite a pointer to the object living on?

Chris Cain via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Aug 16 15:43:20 PDT 2014


On Saturday, 16 August 2014 at 22:36:51 UTC, 岩倉 澪 wrote:
> void changeState(){
>      if(nextState != "WaitState" && nextState != "ExitState"){
>          auto newState = cast(IState)
> Object.factory("game.states."~nextState);
>          import std.exception;
>          enforce(newState);
// !!!!!!!!!!!!!!!
>          currentState = &newState;
// !!!!!!!!!!!!!!!
>          nextState = "WaitState";
>      }
> }

> However, it appears that the changeState function has a bug.
> I believe the problem is that when changeState returns, newState
> gets garbage collected, despite currentState pointing to it.
> I come from a C++ background, so I am not used to garbage
> collection.
> Normally the changeState function would explicitly free the old
> state, and allocate the new one.
>
> Am I correct that newState is liable to be collected after
> changeState returns?
> Is there an easy fix?
> Is my design fundamentally flawed within the context of garbage
> collection?
> If so, what kind of design would you recommend instead?

This is actually not garbage collection. &newState is making a
pointer to a reference that is located on the stack (that is,
when you return from that function
you now have a pointer that may at any time become overwritten
and made invalid.)

As it turns out, interfaces/classes in D are already reference
types, so you can just do something like this:

IState currentState; // reference to an IState

void changeState(){
       if(nextState != "WaitState" && nextState != "ExitState"){
           auto newState = cast(IState)
Object.factory("game.states."~nextState);
           import std.exception;
           enforce(newState);
           currentState = newState; // changed
           nextState = "WaitState";
       }
}


More information about the Digitalmars-d-learn mailing list