Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可能的.NET JIT调用参数生存期错误?_C#_.net_Garbage Collection_Jit - Fatal编程技术网

C# 可能的.NET JIT调用参数生存期错误?

C# 可能的.NET JIT调用参数生存期错误?,c#,.net,garbage-collection,jit,C#,.net,Garbage Collection,Jit,我一直在寻找我们的一个.NET服务由于.NET运行时的内部错误(退出代码0x80131506)而间歇性崩溃的原因。所讨论的服务不执行通常会导致此类错误的任何类型的操作(不安全代码、PInvoke等)。我尝试过如中所述禁用并发GC,以及切换到服务器GC,但间歇性崩溃仍然存在。在调试模式下编译时,.NET 4.7.2和早期版本会出现此问题 public void Repro(int p1, object p2, object p3, object p4, object[] p5) { //

我一直在寻找我们的一个.NET服务由于.NET运行时的内部错误(退出代码0x80131506)而间歇性崩溃的原因。所讨论的服务不执行通常会导致此类错误的任何类型的操作(不安全代码、PInvoke等)。我尝试过如中所述禁用并发GC,以及切换到服务器GC,但间歇性崩溃仍然存在。在调试模式下编译时,.NET 4.7.2和早期版本会出现此问题

public void Repro(int p1, object p2, object p3, object p4, object[] p5)
{
    // Incorrect GC Info generated for this call
    ReproHelper(p1, p2, p3, p4, p5[p1]);
}

public void ReproHelper(int p1, object p2, object p3, object p4, object p5)
{
    Console.WriteLine(p1);
    Console.WriteLine(p2);
    Console.WriteLine(p3);
    Console.WriteLine(p4);
    Console.WriteLine(p5);
}
该服务广泛使用了旧版本的NHibernate(2.0.1),当我在调试器中检查崩溃转储时,当错误发生时,调用堆栈中总是有NHibernate代码,尽管NHibernate本身都是托管代码,因此不应该能够导致这种崩溃

我在调试器下成功地再现了崩溃,启用了GC压力日志和堆验证,虽然它似乎指向JIT/GC中的一个问题,但我不确定是否正确解释了输出

看看发生崩溃的线程,在这种情况下,它发生在
clr!JIT_Stelem_Ref

clr!JIT_Stelem_Ref+0x18: cmp     r9,qword ptr [r8] ds:aaaaaaaa`aaaaaaaa=????????????????
在这种情况下,
0xaa
s字符串似乎是启用HeapVerify的结果,这会导致GC填充收集的内存区域,可能是为了更容易识别,并表明我们仍然有对收集/重新定位对象的旧位置的引用

回溯堆栈中,有大量
0xaaaaaa
条目,但是当最近的GC发生时,这些条目不再出现在调用堆栈顶部的方法中,在本例中,这是根据该线程上最近的GC的GC压力日志:

(注意:为了便于阅读,我颠倒了SOS’
!dumplog
输出中记录行的顺序):

此方法的堆栈区域如下所示:

00000000`1e6ed470 000000003b1a7358 ✕
00000000`1e6ed478 000000000291e3d0 
00000000`1e6ed480 0000000000000000 
00000000`1e6ed488 0000000000000000 
00000000`1e6ed490 000000000662a900 
00000000`1e6ed498 0000000006523c80 
00000000`1e6ed4a0 0000000000000000 
00000000`1e6ed4a8 0000000000000000 
00000000`1e6ed4b0 0000000000000000 
00000000`1e6ed4b8 0000000000000000 
00000000`1e6ed4c0 000000003ac89f08 ✔
00000000`1e6ed4c8 0000000000000000 
00000000`1e6ed4d0 0000000006524248 
00000000`1e6ed4d8 000000003ac89d00 ✔
00000000`1e6ed4e0 0000000000000000 
00000000`1e6ed4e8 000000003ac89cb8 ✔
00000000`1e6ed4f0 0000000000000000 
00000000`1e6ed4f8 000000003ac89d00 ✔
00000000`1e6ed500 0000000100000000 
00000000`1e6ed508 0000000c0000000b 
00000000`1e6ed510 0000000006621660 
00000000`1e6ed518 000000001e6ed690 
00000000`1e6ed520 000000001e6ed6a0
我已将GC压力日志中提到的4个条目指示为重新定位,它们已使用新地址正确更新,但是第一个堆栈条目(
00000000 3B1A7358
-an
NHibernate.Engine.EntityKey
),虽然它是重新定位的对象之一,但未使用新地址更新。如果不再使用它,这当然是完全正常的,但是实际上它将作为参数传递给to

instancenotyetload()
接受9个参数(加上
this
),我在下面的程序集列表中标记了每个参数加载到堆栈/寄存器中的位置。我还包括了SOS’的相关输出!gcinfo因为它与堆栈上的每个参数相关:

Param Address              Instruction                        GC Info
      000007fe`945e3071    mov     r9,qword ptr [rbp-38h]
  P4> 000007fe`945e3075    mov     qword ptr [rsp+20h],r9
      000007fe`945e307a    mov     r9d,dword ptr [rbp-18h]    +sp+20
      000007fe`945e307e    mov     rcx,qword ptr [rbp+40h]
      000007fe`945e3082    cmp     r9,qword ptr [rcx+8]
      000007fe`945e3086    jb      000007fe`945e308d
      000007fe`945e3088    call    clr!JIT_RngChkFail
      000007fe`945e308d    lea     rcx,[rcx+r9*8+10h]         -sp+20
      000007fe`945e3092    mov     r9,qword ptr [rcx]
-- GC Occurred Here --
  P5> 000007fe`945e3095    mov     qword ptr [rsp+28h],r9
      000007fe`945e309a    mov     r9,qword ptr [rbp+38h]     +sp+28
  P6> 000007fe`945e309e    mov     qword ptr [rsp+30h],r9
      000007fe`945e30a3    mov     r9,qword ptr [rbp+30h]     +sp+30
  P7> 000007fe`945e30a7    mov     qword ptr [rsp+38h],r9
      000007fe`945e30ac    mov     r9,qword ptr [rbp+48h]     +sp+38
  P8> 000007fe`945e30b0    mov     qword ptr [rsp+40h],r9
      000007fe`945e30b5    mov     r9,qword ptr [rbp+50h]     +sp+40
  P9> 000007fe`945e30b9    mov     qword ptr [rsp+48h],r9
      000007fe`945e30be    mov     r9d,dword ptr [rbp-18h]    +sp+48
      000007fe`945e30c2    mov     rcx,qword ptr [rbp+20h]
      000007fe`945e30c6    cmp     r9,qword ptr [rcx+8]
      000007fe`945e30ca    jb      000007fe`945e30d1
      000007fe`945e30cc    call    clr!JIT_RngChkFail
      000007fe`945e30d1    lea     rcx,[rcx+r9*8+10h]         -sp+48 -sp+40 -sp+38 -sp+30 -sp+28
  P3> 000007fe`945e30d6    mov     r9,qword ptr [rcx]
this> 000007fe`945e30d9    mov     rcx,qword ptr [rbp+10h]
  P1> 000007fe`945e30dd    mov     rdx,qword ptr [rbp+18h]
  P2> 000007fe`945e30e1    mov     r8d,dword ptr [rbp-18h]
      000007fe`945e30e5    call    InstanceNotYetLoaded(...)
崩溃前的GC发生在
00000 7FE945E3095
,这是在参数4加载到堆栈之后(在
00000 7FE945E3075
),但根据GC信息,也是在该堆栈条目失效之后(在
00000 7FE945E308D
),这就解释了为什么GC重新定位阶段没有更新这个引用

看起来参数5-9的GC信息也错误地过早地将它们标记为dead,而且在这两种情况下,它们都在数组索引范围检查之后立即被标记为dead

在我看来,这就像一个JIT错误,错误地跟踪了这些堆栈参数的生命周期。该分析是否正确,如果正确,最好在哪里报告。如果这不是一个JIT错误,那么我遗漏了什么可以解释这些纯托管代码上的意外崩溃呢

编辑: 我相信下面的代码片段将重现这个问题,至少在调试模式下生成错误的GC信息

public void Repro(int p1, object p2, object p3, object p4, object[] p5)
{
    // Incorrect GC Info generated for this call
    ReproHelper(p1, p2, p3, p4, p5[p1]);
}

public void ReproHelper(int p1, object p2, object p3, object p4, object p5)
{
    Console.WriteLine(p1);
    Console.WriteLine(p2);
    Console.WriteLine(p3);
    Console.WriteLine(p4);
    Console.WriteLine(p5);
}
本质上,必须有对方法的方法调用,该方法:

  • 需要在堆栈上传递至少2个参数(即实例方法至少5个参数)
  • 在堆栈上传递的第二个参数(参数5)必须是数组访问的结果
当满足这些条件时,第四个参数被加载到调用的堆栈中,堆栈条目被正确标记为包含引用。但是,在确定参数5的值时,会进行数组索引范围检查,在这之后,参数4的堆栈项被标记为死


如果GC在范围检查之后但在实际调用发生之前发生,并且GC导致作为参数4传递的对象被重新定位,则当方法恢复时,调用将把旧(无效)地址传递给参数4,而不是新地址。

虽然这不是问题的答案,我这样对待它,因为我确认它是一个bug,应该由.NET团队修复

在.NET Framework 4.7.1(clrjit.dll版本4.7.2xxx)上运行代码段时,生成了正确的GCInfo(实际上,
+sp+20
仅在调用
ReproHelper
之前写入):

但升级到.NET Framework 4.7.2(clrjit.dll版本4.7.3062)后,它不再正确(
+sp+20
在数组索引范围检查之前写入,正确设置,但之后突然取消设置,同时仍在
ReproHelper
调用中使用):


感谢您在提供此错误报告的同时提供如此详细的调查


Microsoft将在即将发布的4.7.2服务版本中修复此问题。

我无法进行分析,但一旦您相对确定这是一个可能仍会影响Microsoft新产品的问题,您可以在此处报告:我报告了Win32 framework和cmake支持中的错误,两个都在几个月内修复好了。但是…我能够生成复制我的说明。通过打开支持案例并与Microsoft支持团队共享转储。我可以在
00007ffb`99450630 55              push    rbp
00007ffb`99450631 4883ec40        sub     rsp,40h
00000003 is a safepoint: 
00007ffb`99450635 488d6c2440      lea     rbp,[rsp+40h]
00007ffb`9945063a 33c0            xor     eax,eax
00007ffb`9945063c 488945f8        mov     qword ptr [rbp-8],rax
00007ffb`99450640 48894d10        mov     qword ptr [rbp+10h],rcx
00007ffb`99450644 895518          mov     dword ptr [rbp+18h],edx
00007ffb`99450647 4c894520        mov     qword ptr [rbp+20h],r8
00007ffb`9945064b 4c894d28        mov     qword ptr [rbp+28h],r9
interruptible
+rbp+28 +rbp+20 +rbp+10 +rbp-8
00007ffb`9945064f 833d3a3fefff00  cmp     dword ptr [00007ffb`99344590],0
00007ffb`99450656 7405            je      00007ffb`9945065d
00007ffb`99450658 e863eaab5f      call    clr!JIT_DbgIsJustMyCode (00007ffb`f8f0f0c0)
00007ffb`9945065d 90              nop
00007ffb`9945065e 8b5518          mov     edx,dword ptr [rbp+18h]
00007ffb`99450661 4c8b4538        mov     r8,qword ptr [rbp+38h]
+r8
00007ffb`99450665 413b5008        cmp     edx,dword ptr [r8+8]
00007ffb`99450669 7205            jb      00007ffb`99450670
-rbp-8
00007ffb`9945066b e8f015ac5f      call    clr!JIT_RngChkFail (00007ffb`f8f11c60)
-r8
00007ffb`99450670 488b5538        mov     rdx,qword ptr [rbp+38h]
+rdx
00007ffb`99450674 448b4518        mov     r8d,dword ptr [rbp+18h]
00007ffb`99450678 4d63c0          movsxd  r8,r8d
00007ffb`9945067b 4a8b54c210      mov     rdx,qword ptr [rdx+r8*8+10h]
00007ffb`99450680 488955f8        mov     qword ptr [rbp-8],rdx
+rbp-8
00007ffb`99450684 488b55f8        mov     rdx,qword ptr [rbp-8]
00007ffb`99450688 4889542428      mov     qword ptr [rsp+28h],rdx
+sp+28
00007ffb`9945068d 8b5518          mov     edx,dword ptr [rbp+18h]
-rdx
00007ffb`99450690 4c8b4520        mov     r8,qword ptr [rbp+20h]
+r8
00007ffb`99450694 4c8b4d28        mov     r9,qword ptr [rbp+28h]
+r9
00007ffb`99450698 488b4d30        mov     rcx,qword ptr [rbp+30h]
+rcx
00007ffb`9945069c 48894c2420      mov     qword ptr [rsp+20h],rcx
+sp+20
00007ffb`994506a1 488b4d10        mov     rcx,qword ptr [rbp+10h]
-rbp-8
00007ffe`62290630 55              push    rbp
00007ffe`62290631 4883ec30        sub     rsp,30h
00007ffe`62290635 488d6c2430      lea     rbp,[rsp+30h]
00000007 is a safepoint: 
00007ffe`6229063a 48894d10        mov     qword ptr [rbp+10h],rcx
00007ffe`6229063e 895518          mov     dword ptr [rbp+18h],edx
00007ffe`62290641 4c894520        mov     qword ptr [rbp+20h],r8
00007ffe`62290645 4c894d28        mov     qword ptr [rbp+28h],r9
interruptible
+rbp+28 +rbp+20 +rbp+10
00007ffe`62290649 833d483fefff00  cmp     dword ptr [00007ffe`62184598],0
00007ffe`62290650 7405            je      00007ffe`62290657
00007ffe`62290652 e869f7aa5f      call    clr!TranslateSecurityAttributes+0x857b0 (00007ffe`c1d3fdc0) (JitHelp: CORINFO_HELP_DBG_IS_JUST_MY_CODE)
00007ffe`62290657 90              nop
00007ffe`62290658 488b4d30        mov     rcx,qword ptr [rbp+30h]    
+rcx
00007ffe`6229065c 48894c2420      mov     qword ptr [rsp+20h],rcx
+sp+20
00007ffe`62290661 8b4d18          mov     ecx,dword ptr [rbp+18h]
-rcx
00007ffe`62290664 488b5538        mov     rdx,qword ptr [rbp+38h]
+rdx
00007ffe`62290668 483b4a08        cmp     rcx,qword ptr [rdx+8]
00007ffe`6229066c 7205            jb      00007ffe`62290673
00007ffe`6229066e e8ed22ab5f      call    clr!TranslateSecurityAttributes+0x88350 (00007ffe`c1d42960) (JitHelp: CORINFO_HELP_RNGCHKFAIL)
-sp+20
00007ffe`62290673 488d54ca10      lea     rdx,[rdx+rcx*8+10h]
-rdx +rdx(interior)
00007ffe`62290678 488b0a          mov     rcx,qword ptr [rdx]
+rcx
00007ffe`6229067b 48894c2428      mov     qword ptr [rsp+28h],rcx
+sp+28
00007ffe`62290680 488b4d10        mov     rcx,qword ptr [rbp+10h]
00007ffe`62290684 8b5518          mov     edx,dword ptr [rbp+18h]
-rdx(interior)
00007ffe`62290687 4c8b4520        mov     r8,qword ptr [rbp+20h]
+r8
00007ffe`6229068b 4c8b4d28        mov     r9,qword ptr [rbp+28h]
+r9
00007ffe`6229068f e804faffff      call    00007ffe`62290098 (GCInfoBug.Bug.ReproHelper(Int32, System.Object, System.Object, System.Object, System.Object), mdToken: 0000000006000004)
-sp+28 -r9 -r8 -rcx
00007ffe`62290694 90              nop
00007ffe`62290695 90              nop
not interruptible
-rbp+28 -rbp+20 -rbp+10
00007ffe`62290696 488d6500        lea     rsp,[rbp]
00007ffe`6229069a 5d              pop     rbp
00007ffe`6229069b c3              ret