2012-02-16 23 views
5

Gần đây tôi đã đọc this article bởi Dave Detlefs, trong đó ông trình bày một vài trường hợp CLR thực hiện việc loại bỏ kiểm tra giới hạn mảng. Tôi quyết định thử nghiệm này bản thân mình, vì vậy tôi đã làm như sau:Array Bounds Kiểm tra loại bỏ trong CLR?

  • Mở Visual Studio 2010 Ultimate SP1
  • Tạo một C# dự án mới của loại ứng dụng Console (nhắm mục tiêu NET 4 Client Profile theo mặc định)
  • Added đoạn mã sau (tất cả các tiểu phương pháp được lấy trực tiếp từ các bài báo):

    class Program { 
        static void Main(string[] args) { 
         int[] array = new int[30]; 
         Test_SimpleAscend(array); 
         Test_SimpleRedundant(array, 3); 
    
         foreach (int i in array) { 
          Console.WriteLine(i); 
         } 
        } 
    
        static void Test_SimpleAscend(int[] a) { 
         for (int i = 0; i < a.Length; i++) 
          a[i] = i; 
        } 
    
        static void Test_SimpleRedundant(int[] a, int i) { 
         int k = a[i]; 
         k = k + a[i]; 
        } 
    } 
    
  • Switched chuẩn bị tung ra chế độ; xác nhận rằng "Optimize Mã" được chọn trong các tùy chọn Build

  • Added một breakpoint cho mỗi truy cập mảng, bắt đầu gỡ lỗi (F5) và mở cửa sổ Dissassembly

Vì vậy, đây là dissassembly cho a [i] = tôi; trong Test_SimpleAscend:

   a[i] = i; 
00000024 mov   eax,dword ptr [ebp-4] 
00000027 mov   edx,dword ptr [ebp-8] 
0000002a cmp   eax,dword ptr [edx+4] 
0000002d jb   00000034 
0000002f call  64FD6E08 
00000034 mov   ecx,dword ptr [ebp-4] 
00000037 mov   dword ptr [edx+eax*4+8],ecx 

Kiểm tra cmp/jb/call bị ràng buộc, thực sự buộc cuộc gọi phải được thực thi ném IndexOutOfRangeException.

Điều tương tự cho tất cả các truy cập mảng, bao gồm truy cập dự phòng trong Test_SimpleRedundant. Vì vậy, có cái gì sai với phương pháp thử nghiệm của tôi, hoặc CLR không thực sự loại bỏ giới hạn kiểm tra? Tôi hy vọng tôi là sai và nếu vậy tôi muốn biết làm thế nào tôi thực sự có thể nhận được giới hạn kiểm tra mảng loại bỏ.

+10

Khi bạn nói "bắt đầu gỡ lỗi", tôi giả định rằng bạn đã khởi chạy ứng dụng * với trình gỡ lỗi được đính kèm * từ môi trường Visual Studio. Trong trường hợp đó, bạn cần đảm bảo rằng biên dịch JIT được kích hoạt vì nó không được mặc định. Trình biên dịch JIT là trình biên dịch thực hiện tối ưu hóa này, không phải trình biên dịch C#. –

+0

Bạn mong đợi điều gì xảy ra nếu việc kiểm tra giới hạn bị vô hiệu hóa? Đây thường là tính năng mà mọi người mong đợi khi sử dụng ngôn ngữ được quản lý như C#. –

+1

Cách dễ nhất để đảm bảo tối ưu hóa thực sự được kích hoạt để khởi động ứng dụng mà không cần gỡ lỗi và sau đó đính kèm trình gỡ rối vào nó. – svick

Trả lời

12

Nhờ một lời nhận xét của Cody Grey, tôi đã quản lý để trả lời câu hỏi của riêng tôi:

Theo mặc định, tối ưu hóa JIT bị vô hiệu hóa khi gỡ lỗi. Để khắc phục điều này, bạn có thể vào Debug -> Options and Settings -> Debugging -> General, và bỏ chọn cả "Enable Just My Code" và "Suppress JIT Optimization on load module".

Cũng thấy http://msdn.microsoft.com/en-us/library/ms241594.aspx

Khi bật tối ưu hóa, kiểm tra giới hạn sẽ bị xóa như được quảng cáo.

Tôi sẽ để tài liệu này ở đây cho mục đích tài liệu.

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