.net 涉及gcroot的崩溃<&燃气轮机;以及在本机线程运行时的垃圾收集 我有本地C++对象 Objuts1/Cuth>持有对托管的引用: class Object1 { Object2* parent_; gcroot<Observer^> obs_; // ctor Object1(Object2* parent, Observer^ obs) : parent_(parent), obs_(obs) {} void Execute(void) { parent_->Execute2(obs_); } };

.net 涉及gcroot的崩溃<&燃气轮机;以及在本机线程运行时的垃圾收集 我有本地C++对象 Objuts1/Cuth>持有对托管的引用: class Object1 { Object2* parent_; gcroot<Observer^> obs_; // ctor Object1(Object2* parent, Observer^ obs) : parent_(parent), obs_(obs) {} void Execute(void) { parent_->Execute2(obs_); } };,.net,garbage-collection,c++-cli,.net,Garbage Collection,C++ Cli,用例是创建Object1并将其放入队列。然后一个单独的本机线程弹出队列, 调用Execute->Execute2->OnNext(),然后删除非托管的Object1 托管对象恰好从接口IObserver派生并实现反应式扩展,因此我对其调用OnNext()。 显然,在重载情况下(意味着调用了GC),由于InvalidOperationException(“句柄未初始化”)程序崩溃 使用以下崩溃转储堆栈(已清理以使其更具可读性): C++/CLI代码: StoreObserver(Obse

用例是创建
Object1
并将其放入队列。然后一个单独的本机线程弹出队列, 调用Execute->Execute2->OnNext(),然后删除非托管的
Object1

托管对象恰好从接口
IObserver
派生并实现反应式扩展,因此我对其调用
OnNext()
。 显然,在重载情况下(意味着调用了GC),由于InvalidOperationException(“句柄未初始化”)程序崩溃 使用以下崩溃转储堆栈(已清理以使其更具可读性):

C++/CLI代码:

     StoreObserver(Observer^ obs)
     {
       Object1 obj1 = new Object1(ptrObject2, obs);
我倾向于排除1作为原因,因为只有在删除
Object1
时才会调用gcroot析构函数。直到最后一天,这种情况才会发生 已返回执行调用。因此,GC不应该收集由
gcroot
持有的托管对象

2似乎是可能的,因为GC不知道非托管线程,这些线程可以在GC进程的“中间”执行。 通常,您会发现这样一条语句,即存储在gcroot中的托管对象不需要固定。这似乎是正确的 应该是这样的

我很难想象3是如何发生的

有谁能解释一下这一点,或者支持或者证明我的推理是错误的?
崩溃是间歇性的,在尝试使用固定指针之前,我需要一些反馈。

4。一个标准的堆损坏错误重写了gcroot。好的,所以我可以在原生对象的gcroot周围放置一些前哨字节,以尝试确认这一点。不过,你觉得1或3个不太可能吗。当GC更新gcroot中的位置时,另一个线程使用了它,并看到一个部分更新的值(我不知道底层类型是否为原子)。这不应该是一个问题,因为只有托管代码可以从gcroot读取,并且它应该在gc期间暂停。。。但是比第一个选项更可能。@BenVoigt只能从gcroot读取托管代码,并且应该在gc期间暂停-但是在混合模式下,本机代码转换为托管代码并返回时,此代码似乎只能在本机线程上执行?!或者转换是否自动意味着线程切换?没有线程切换。但是垃圾收集器应该知道所有正在运行的托管代码,即使线程是由本机代码创建的。
[Managed to Native Transition]  
mscorlib.dll!System.Runtime.InteropServices.GCHandle.FromIntPtr(System.IntPtr value)
<Module>.gcroot<Observer^>.->()
<Module>.Object2.Execute2(Observer obs)
<Module>.Object1.Execute() 
[Native to Managed Transition]  
     Observer obs = new Observer;
     SomeManagedObject.StoreObserver(obs);
     StoreObserver(Observer^ obs)
     {
       Object1 obj1 = new Object1(ptrObject2, obs);