2015-07-22 19 views
35

Sau khi nâng cấp gần đây lên .net 4.6, chúng tôi phát hiện ra lỗi mà RyuJit tạo kết quả không chính xác, chúng tôi có thể giải quyết vấn đề này bằng cách thêm useLegacyJit enabled = "true" vào app.config.RyuJit tạo kết quả không chính xác

Tôi làm cách nào để gỡ lỗi mã máy được tạo bởi những điều sau đây?

Tôi đã tạo một dự án bảng điều khiển mới trong VS 2015 RTM, được đặt thành Phát hành, Mọi CPU, không được chọn Ưu tiên 32 bit, chạy cùng và không kèm theo trình gỡ lỗi tạo ra cùng một kết quả.

using System; 
using System.Runtime.CompilerServices; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(Calculate()); 
      Console.WriteLine(Calculate()); 

      Console.ReadLine(); 
     } 

     [MethodImpl(MethodImplOptions.AggressiveInlining)] 
     public static Value Calculate() 
     { 
      bool? _0 = (bool?)null; 
      bool? _1 = (bool?)true; 
      if (!Value.IsPresent<bool>(_1)) 
      { 
       return default(Value); 
      } 

      bool? result = null; 
      result = (_1.Value ? new bool?(false) : result); 
      if (_0.HasValue && _0.Value) 
      { 
      } 
      return new Value(result); 
     } 

     public struct Value 
     { 
      bool? _value; 

      public Value(bool? value) 
      { 
       _value = value; 
      } 

      public static bool IsPresent<T>(bool? _) 
      { 
       return _.HasValue; 
      } 

      public override string ToString() 
      { 
       return _value.ToString(); 
      } 
     } 
    } 
} 

Nó nên sản xuất: False False

nhưng thay vào đó nó tạo ra: Đúng False

Phần chính của ví dụ này là

result = true ? false : result; 

mà phải luôn luôn trở lại sai, nhưng như bạn có thể thấy từ đầu ra, nó trả về True lần đầu tiên phương thức của anh ta được chạy và một câu trả lời khác vào lần thứ hai phương thức được chạy. Việc loại bỏ một số dòng khác khỏi phương thức Calculate() sẽ làm cho nó trả về True luôn, nhưng ví dụ được đưa ra là gần nhất mà tôi có thể tạo lại cho kịch bản sản xuất thực tế của chúng ta.

+5

Vâng, đó là lỗi tối ưu hóa nội tuyến. Hàm Calculate inlined đầu tiên() có một lệnh xấu. Hình như tôi có một '!' Ở đâu đó bên trong trình tối ưu hóa không nên ở đó. Không có gì chúng tôi có thể làm để sửa lỗi này tất nhiên, bạn có thể báo cáo nó tại connect.microsoft.com. Chỉ cần lay off MethodImplOptions.AggressiveInlining trong một thời gian, đó là dường như không được thử nghiệm rộng rãi. –

+0

Mã sản xuất thực tế không có thuộc tính AggressiveInlining, nhưng đó là cách duy nhất tôi có thể tái tạo hành vi trong ví dụ nhỏ này. Mã sản xuất đang được tạo ra một phần, đó là lý do tại sao mã ví dụ trông hơi lạ. Tôi vừa báo cáo nó tại https://connect.microsoft.com/VisualStudio/feedback/details/1578173 – BrandonAGr

+0

@BrandonAGr Lỗi này gây ra khi nội tuyến? Sử dụng 'MethodImplOptions.NoInlining' là một công việc có thể xung quanh? – Andre

Trả lời

27

Cảm ơn bạn đã tham gia chương trình repro bị cô lập và tôi có thể xác nhận rằng đây thực sự là lỗi RyuJIT trong trình tối ưu hóa đã được hiển thị do nội tuyến. Tôi đã thực hiện một sửa chữa cho trình biên dịch và tìm ra các chi tiết triển khai. Không được biến SO thành trình theo dõi lỗi và để quay vòng nhanh hơn: [email protected]

+3

Tôi đã xây dựng một phiên bản đơn giản của mã nguồn, bạn có thể tìm thấy nó trong repo coreclr: https : //github.com/dotnet/coreclr/issues/1299 – AndreyAkinshin

+1

@HansPassant Yeah không có ý định này như là một báo cáo lỗi, loại câu hỏi ẩn là làm thế nào để tìm mã máy đang được thực thi. Ví dụ đơn giản của Andrey được tạo ra rất dễ dàng để xem việc tháo gỡ trong studio trực quan, tất nhiên nó vẫn không dễ dàng nhận ra những thanh ghi nào đang giữ gì nhưng tôi có thể đi qua nó – BrandonAGr

+0

@schellap : //connect.microsoft.com/VisualStudio/Feedback/Details/1602437? –

Các vấn đề liên quan