我最近阅读了 Dave Detlefs 的这篇文章,他在其中介绍了 CLR 执行数组边界检查消除的几个案例。我决定自己测试一下,所以我做了以下事情:
- 打开 Visual Studio 2010 Ultimate SP1
- 创建了一个控制台应用程序类型的新 C# 项目(默认针对 .NET 4 客户端配置文件)
添加以下代码(所有子方法均直接取自文章):
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]; } }
切换到释放模式;验证在构建选项中选中了“优化代码”
- 为每个数组访问添加断点,开始调试(F5)并打开反汇编窗口
所以这里是 a[i] = i; 的反汇编。在 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
cmp/jb/call 是边界检查,实际上强制执行调用会引发 IndexOutOfRangeException。
所有数组访问都一样,包括 Test_SimpleRedundant 中的冗余访问。那么我的测试方法是否有问题,或者 CLR 实际上并没有消除边界检查?我希望我错了,如果是这样,我想知道如何才能真正获得数组边界检查消除。