Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.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# 我想我的团队在64位编译器中发现了一个bug,其他人能确认或者告诉我为什么这是正确的吗?_C#_.net_Debugging - Fatal编程技术网

C# 我想我的团队在64位编译器中发现了一个bug,其他人能确认或者告诉我为什么这是正确的吗?

C# 我想我的团队在64位编译器中发现了一个bug,其他人能确认或者告诉我为什么这是正确的吗?,c#,.net,debugging,C#,.net,Debugging,我有一个简单的关于这个可能的bug的洁净室示例 static void Main(string[] args) { bool MyFalse = false; if (MyFalse) { throw new Exception(); } try { int i = 0; } catch (Exceptio

我有一个简单的关于这个可能的bug的洁净室示例

   static void Main(string[] args)
    {
        bool MyFalse = false;

        if (MyFalse)
        {
            throw new Exception();
        }
        try
        {
            int i = 0;
        }
        catch (Exception e)
        {
            Console.Write(e);
        }

        Console.Read();
    }
如果在x64或AnyCPU中编译(当VS2012中preferred 32bit设置为false时),如果在If块中放置断点,则始终命中该断点

我们在VS2012、VS2010和VS2008中试过,它们在64位编译时都触发了if块,但在32位编译时却没有触发if块

我们查看了32位和64位版本的IL,它们看起来是一样的

我们在生产代码中发现了这一点,因为无论布尔变量的值是多少,都会运行if块并引发异常,尽管在这个简单的示例中,我们似乎无法引发异常,它是在生产代码中发生的。

因为它发生在生产代码中,所以它不仅仅是一个调试器问题

非常奇怪的行为,但似乎没有实际运行if块中的任何代码。开发者认为这是他所看到的一个例外,于是立即采取行动

(所有调试均处于调试模式-生产正在发布)


如果抛出被注释掉-未达到If块。

在优化代码中,MSIL与本机机器代码和源代码之间没有严格的相关性。这会导致调试器有时高亮显示与正在执行的代码不同的代码,在单步执行时多次高亮显示同一行,或者将断点放置在与预期位置不同的位置


这是调试优化代码的一个基本问题,表示调试信息格式的不足。编译器或调试器中都没有bug。您可能需要在反汇编视图中进行调试。

好的,我明白了。在64位调试器的调试构建中,这确实会出错。关键是准确地在if()语句上设置断点,然后开始单步执行。看起来好像正在执行throw语句。但如果实际情况并非如此,那么实际的代码执行是正确的

要查看发生了什么,请让它进入throw语句行。然后使用调试+反汇编查看它的实际位置。在我的机器上,它看起来像这样:

       if (MyFalse)
00000040  movzx       ecx,byte ptr [rbp+8] 
00000044  xor         eax,eax 
00000046  test        ecx,ecx 
00000048  sete        al 
0000004b  mov         dword ptr [rbp+1Ch],eax 
0000004e  movzx       eax,byte ptr [rbp+1Ch] 
00000052  mov         byte ptr [rbp+18h],al 
00000055  movzx       eax,byte ptr [rbp+18h] 
00000059  test        eax,eax 
0000005b  jne         0000000000000088            // <=== Note this jump
        {
0000005d  nop 
            throw new Exception();
0000005e  lea         rcx,[5B848928h] 
00000065  call        000000005F65E9E0 
0000006a  mov         qword ptr [rbp+20h],rax 
0000006e  mov         rax,qword ptr [rbp+20h] 
00000072  mov         qword ptr [rbp+28h],rax 
00000076  mov         rcx,qword ptr [rbp+28h] 
0000007a  call        000000005BE4A5D0 
0000007f  mov         rcx,qword ptr [rbp+28h] 
00000083  call        000000005F73E36C 
00000088  nop                                     // <=== yellow arrow here
        }
        try
        {
00000089  nop 
            int i = 0;
if(MyFalse)
000000 40 movzx ecx,字节ptr[rbp+8]
00000044异或eax,eax
00000046测试ecx,ecx
00000048塞特艾尔
000000 4B mov dword ptr[rbp+1Ch],eax
0000004e movzx eax,字节ptr[rbp+1Ch]
000000 52 mov字节ptr[rbp+18h],al
00000055 movzx eax,字节ptr[rbp+18h]
00000059测试eax,eax

0000005b jne 00000000000000 88//听起来更像是调试器将断点放在错误的位置。是否引发异常?如果断点设置在没有代码的行上,IDE是否会将断点移动到下一个有代码的行。既然编译器可以删除
if
,这就是发生的事情吗?我明白你在说什么了。您可以像执行一样进入
throw new Exception()
行,但显然不是这样,因为没有引发异常,也不会触发断点。@NeilKnight:断点的存在是否会改变行为(即,异常仅在有断点时发生,或者总是发生?)如果程序是在调试模式下构建的,那么这听起来像一个bug;您可以在connect.microsoft.com上报告。如果它是在发布模式下构建的,那么这是意料之中的;调试器在调试未在调试模式下编译的代码方面做得很差。(正如Raymond所说,我简直不敢相信我必须这么说。:-)@Magnus:在.NET中进行拆分编译的副作用:优化分为两个阶段:在转换为MSIL的过程中,以及在JIT转换为本机机器代码的过程中。您确定它们都被禁用了吗?只有生成属性中的一个。(不知道其他的)@Magnus:你可以使用Reflector(或dotPeek等)检查C#编译器是否添加了
DebuggableAttribute
并设置
禁用优化
。在附加调试器时,Visual Studio的配置还可以禁止(或不禁止)优化。那么为什么它只对64位而不是32位执行优化?这个答案的最大问题是,它没有解释为什么在未优化的代码中会出现错误。这不是正确的答案。“轻微的困惑”我曾经有过类似的事情,那就是调试器在向我撒谎;有几个小时,我感到非常困惑