私は最近、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 は境界チェックを実際に排除していませんか? 私が間違っていることを願っています。そうであれば、配列の境界チェックの削除を実際に取得する方法を知りたいです。