首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当断点编辑参数到System.Numerics函数的x64构建时,为什么要获得x64?

当断点编辑参数到System.Numerics函数的x64构建时,为什么要获得x64?
EN

Stack Overflow用户
提问于 2021-06-03 23:29:07
回答 3查看 301关注 0票数 4

在AnyCPU或x86上,我可以运行这个程序,在Foo上设置一个断点,将第一个参数从0.5f编辑到0.6f,然后恢复正常。然而,在x64上,它在恢复时总是与FatalExecutionEngineError崩溃。

代码语言:javascript
复制
using System;
using System.Numerics;

public static class Interaction
{
    public static void Main(string[] args)
    {
        while (true)
        {
            Console.WriteLine(Foo.M11);
            System.Threading.Thread.Sleep(0);
        }
    }

    private static Matrix4x4 Foo
    {
        get
        {
            return Matrix4x4.CreateFromYawPitchRoll(0.5f /* breakpoint and set this to 0.6f*/, 0.5f, 0.5f);
        }
    }
}

至少,它发生在.NET框架4.7.2和.NET Framework4.6.2上。我有办法解决这个问题吗?

编辑:在.NET Framework4.8上测试它,在阅读了他们在该版本中修复了一些x64内容之后,它仍然在崩溃!

EN

回答 3

Stack Overflow用户

发布于 2021-06-13 13:56:27

当在返回结构的方法上使用编辑和继续时,这似乎是.NET核心和.NET框架中的一个已知问题。(请参阅GitHub:EnC:结构返回方法编辑后的ExecutionEngineException上的相关问题)。

关于这个问题的评论表明它可能在.NET 6中得到修正。

编辑:

深入研究这个问题后,似乎是因为在对当前运行的方法应用编辑和继续更改时,“变量号”(分配给每个局部变量的内部索引)的处理出现了符号/无符号不匹配。

当应用编辑和继续更改时,运行时分配数组来保存更改前后的局部变量信息,但是它必须考虑到以下事实:有多达4个具有负变量数(-1到-4)的“特殊”局部变量,因此它用4个额外条目分配数组,然后在每个局部变量编号中添加4个,以确定应该在相应数组中写入的索引。

不幸的是,变量号存储在无符号字段中,在确定数组索引时,忽略了对有符号值的转换,因此对于特殊的局部变量,它计算的是一个大型正索引,试图注销数组的末尾并导致访问冲突,而不是写入数组的开头。

这些“特殊”局部变量之一是用于从方法返回结构的内存,这就是为什么问题中的方法(以及任何返回结构的方法)都会触发这个问题。

票数 2
EN

Stack Overflow用户

发布于 2021-06-13 03:37:22

我也复制了这个问题,有几个有趣的观察:

  • 问题是特定于堆栈框架的--如果在调试器位于同一堆栈帧时尝试编辑const,则会出现问题,但如果调试器位于其他任何地方(例如,在Console.WriteLine(Foo.M11);),则可以很好地编辑const。
  • 问题是特定于结构的-我设法用我自己的结构来重复这个问题,这些结构是在单独的程序集中定义的,并打开了‘优化代码’选项。不能重复上课。

我怀疑新Jit,实际上我已经编辑并继续使用遗留JIT。您可以通过将以下部分添加到app.config来启用它

代码语言:javascript
复制
  <runtime>
    <useLegacyJit enabled="1" />
  </runtime>

仍然检查程序集代码为什么编辑和继续在RuiJIT中失败,但是您可以使用@Misha中的变通方法,或者,如我所建议的,在堆栈框架之外使用遗留jit进行调试或更改const。

RuiJIT (repro)

代码语言:javascript
复制
        private static Matrix4x4 Foo => Matrix4x4.CreateFromYawPitchRoll(0.6f /* breakpoint and set this to 0.6f*/, 0.5f, 0.5f);
00007FFCECF609B2  push        rsi  
00007FFCECF609B3  sub         rsp,70h  
00007FFCECF609B7  vzeroupper  
00007FFCECF609BA  mov         rbp,rsp  
00007FFCECF609BD  xor         eax,eax  
00007FFCECF609BF  mov         qword ptr [rbp+68h],rax  
00007FFCECF609C3  mov         qword ptr [rbp+90h],rcx  
00007FFCECF609CA  cmp         dword ptr [7FFCECE545C8h],0  
00007FFCECF609D1  je          00007FFCECF609D8  
00007FFCECF609D3  call        00007FFD4C98CBA0  
00007FFCECF609D8  lea         rcx,[rbp+28h]  
00007FFCECF609DC  vmovss      xmm1,dword ptr [7FFCECF60A48h]  
00007FFCECF609E5  vmovss      xmm2,dword ptr [7FFCECF60A4Ch]  
00007FFCECF609EE  vmovss      xmm3,dword ptr [7FFCECF60A50h]  
00007FFCECF609F7  call        00007FFD53107740  
00007FFCECF609FC  mov         rax,qword ptr [rbp+90h]  
00007FFCECF60A03  vmovdqu     xmm0,xmmword ptr [rbp+28h]  
00007FFCECF60A09  vmovdqu     xmmword ptr [rax],xmm0  
00007FFCECF60A0E  vmovdqu     xmm0,xmmword ptr [rbp+38h]  
00007FFCECF60A14  vmovdqu     xmmword ptr [rax+10h],xmm0  
00007FFCECF60A1A  vmovdqu     xmm0,xmmword ptr [rbp+48h]  
00007FFCECF60A20  vmovdqu     xmmword ptr [rax+20h],xmm0  
00007FFCECF60A26  vmovdqu     xmm0,xmmword ptr [rbp+58h]  
00007FFCECF60A2C  vmovdqu     xmmword ptr [rax+30h],xmm0  
00007FFCECF60A32  mov         rax,qword ptr [rbp+90h]  
00007FFCECF60A39  lea         rsp,[rbp+70h]  
00007FFCECF60A3D  pop         rsi  
00007FFCECF60A3E  pop         rdi  
00007FFCECF60A3F  pop         rbp  
00007FFCECF60A40  ret  

遗留JIT (无复制)

代码语言:javascript
复制
        private static Matrix4x4 Foo => Matrix4x4.CreateFromYawPitchRoll(0.6f /* breakpoint and set this to 0.6f*/, 0.5f, 0.5f);
00007FFCECF609C2  and         al,8  
00007FFCECF609C5  push        rbp  
00007FFCECF609C6  sub         rsp,30h  
00007FFCECF609CA  mov         rbp,rsp  
00007FFCECF609CD  mov         rax,7FFCECE545C8h  
00007FFCECF609D7  mov         eax,dword ptr [rax]  
00007FFCECF609D9  test        eax,eax  
00007FFCECF609DB  je          00007FFCECF609E2  
00007FFCECF609DD  call        00007FFD4C98CBA0  
00007FFCECF609E2  movss       xmm3,dword ptr [7FFCECF60A18h]  
00007FFCECF609EA  movss       xmm2,dword ptr [7FFCECF60A18h]  
00007FFCECF609F2  movss       xmm1,dword ptr [7FFCECF60A20h]  
00007FFCECF609FA  mov         rcx,qword ptr [rbp+40h]  
00007FFCECF609FE  call        00007FFD53107740  
00007FFCECF60A03  mov         qword ptr [rbp+20h],rax  
00007FFCECF60A07  mov         rax,qword ptr [rbp+40h]  
00007FFCECF60A0B  jmp         00007FFCECF60A0D  
00007FFCECF60A0D  nop  
00007FFCECF60A0E  lea         rsp,[rbp+30h]  
00007FFCECF60A12  pop         rbp  
00007FFCECF60A13  ret  
票数 0
EN

Stack Overflow用户

发布于 2021-06-12 14:09:40

我成功地在运行在VS 2019年和.NET 5上的计算机上复制了同样的问题。

这似乎是一个与直接储存器相关的微软内部bug。在x64中,它的工作方式不同于x86。

您可以使用托管调试助理对其进行优化。

一种可能的解决方法是在调试时添加一个变量并从手表中更新其值:

代码语言:javascript
复制
private static Matrix4x4 Foo
{
    get
    {
        float yaw = 0.5f;
        return Matrix4x4.CreateFromYawPitchRoll(yaw, 0.5f, 0.5f);
    }
}
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67829796

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档