【发布时间】:2009-05-07 14:07:11
【问题描述】:
我正在使用 C++/CLI 编写一些托管包装器。问题是 GC 有时会在我使用它的非托管成员时处理该对象。 (我认为这种行为很疯狂,但这是另一个话题)。更多详情见:
Finalizer launched while its object was still being used http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx
我正在寻找一种方便的呼叫方式:
GC::KeepAlive(this);
在每个方法的末尾。对于普通的旧 void 方法,这很容易,但对于返回值的方法,它有点棘手。
int ComputeInt() {
return m_unmanagedMember->LongRunningComputation();
}
必须变成:
int ComputeInt() {
int tmp = m_unmanagedMember->LongRunningComputation();
GC::KeepAlive(this);
return tmp;
}
这对我来说有点难看。
我考虑了一个在 dtor 中调用 GC::KeepAlive 的保护类,但这会在每个方法中引发 ctor 和 dtor 调用,这似乎有点过分。
是否有任何可用的 C++ 魔法可以让我避免临时变量?
编辑
我意识到 try + finally 会为我解决问题,即:
int ComputeInt() {
try {
return m_unmanagedMember->LongRunningComputation();
} finally {
GC::KeepAlive(this);
}
}
最后,我实现了一个宏来处理这个问题:
#define KEEPALIVE_RETURN(x) try {\
return x;\
} finally { System::GC::KeepAlive(this); }
【问题讨论】:
-
我不认为你可以做守卫,因为你必须在非托管类中持有一个托管引用才能做到这一点——如果可以的话,你可以让 ctor 和 dtor 内联,所以这基本上只是一个 KeepAlive 调用(但是,就像我说的,我认为这是不可能的)
-
我遇到了同样的事情:谢谢!我一直在绕圈子,试图找到导致堆损坏的位置,这一切都是由于终结器在对象仍在使用时释放内存...... DOH......
标签: .net c++ garbage-collection finalizer