views:

202

answers:

1

Hi

I'm writing some managed wrappers using C++/CLI. The problem is that the GC sometimes disposes the object while I'm using unmanaged members from it. (I think this behaviour is insane but this is another topic). For more details see:

http://stackoverflow.com/questions/134653/finalizer-launched-while-its-object-was-still-being-used http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx

What I'm looking for is a convenient way to call:

GC::KeepAlive(this);

at the end of every method. For plain old void methods it's easy enough but for methods returning values its a bit more tricky.

int ComputeInt() {
   return m_unmanagedMember->LongRunningComputation();
}

would have to be turned into:

int ComputeInt() {
   int tmp = m_unmanagedMember->LongRunningComputation();
   GC::KeepAlive(this);
   return tmp;
}

This looks a bit ugly to me.

I considered a guard class that calls GC::KeepAlive in the dtor but that would incur a ctor and dtor call in every method which seems a bit excessive.

Is there any C++ magic available that would let me avoid the temp variable?

Edit

I realized that a try + finally would do the trick for me, i.e:

int ComputeInt() {
   try {
      return m_unmanagedMember->LongRunningComputation();
   } finally {
      GC::KeepAlive(this);
   }
}

In the end, I implemented a macro to handle this:

#define KEEPALIVE_RETURN(x) try {\
    return x;\
} finally { System::GC::KeepAlive(this); }
+1  A: 

How about something like (not really checking syntax)

template<class RType>
const RType& KeepAliveRet(Object^ o, const RType& ret)
{
    GC::KeepAlive(o);
    return ret;
} 


int ComputeInt() {
   return KeepAliveRet(this, m_unmanagedMember->LongRunningComputation());
}
Lou Franco