[解決済み】.NET 3.5のJITがアプリケーションの実行時に機能しない。
2022-03-24 01:54:24
質問
以下のコードは、Visual Studio内部でリリースを実行した場合と、Visual Studio外部でリリースを実行した場合とで、異なる出力をもたらします。Visual Studio 2008を使用し、.NET 3.5をターゲットにしています。また、.NET 3.5 SP1も試してみました。
Visual Studio の外で実行すると、JIT が起動するはずです。(a)私が見逃しているC#で何か微妙なことが起こっているのか、(b)JITが実はエラーになっているのか、どちらかでしょう。JITがおかしくなるのは疑問ですが、他に可能性がなくなってきました...。
Visual Studio 内で実行した場合の出力。
0 0,
0 1,
1 0,
1 1,
Visual Studio以外でリリースを実行した場合の出力。
0 2,
0 2,
1 2,
1 2,
その理由は何ですか?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
struct IntVec
{
public int x;
public int y;
}
interface IDoSomething
{
void Do(IntVec o);
}
class DoSomething : IDoSomething
{
public void Do(IntVec o)
{
Console.WriteLine(o.x.ToString() + " " + o.y.ToString()+",");
}
}
class Program
{
static void Test(IDoSomething oDoesSomething)
{
IntVec oVec = new IntVec();
for (oVec.x = 0; oVec.x < 2; oVec.x++)
{
for (oVec.y = 0; oVec.y < 2; oVec.y++)
{
oDoesSomething.Do(oVec);
}
}
}
static void Main(string[] args)
{
Test(new DoSomething());
Console.ReadLine();
}
}
}
解決方法は?
JITオプティマイザのバグです。 内部ループを展開していますが、oVec.yの値を適切に更新していません。
for (oVec.x = 0; oVec.x < 2; oVec.x++) {
0000000a xor esi,esi ; oVec.x = 0
for (oVec.y = 0; oVec.y < 2; oVec.y++) {
0000000c mov edi,2 ; oVec.y = 2, WRONG!
oDoesSomething.Do(oVec);
00000011 push edi
00000012 push esi
00000013 mov ecx,ebx
00000015 call dword ptr ds:[00170210h] ; first unrolled call
0000001b push edi ; WRONG! does not increment oVec.y
0000001c push esi
0000001d mov ecx,ebx
0000001f call dword ptr ds:[00170210h] ; second unrolled call
for (oVec.x = 0; oVec.x < 2; oVec.x++) {
00000025 inc esi
00000026 cmp esi,2
00000029 jl 0000000C
oVec.yを4まで増加させるとバグが消えますが、これはアンロールするための呼び出しが多すぎます。
回避策の1つはこれです。
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
oDoesSomething.Do(new IntVec(x, y));
}
}
UPDATE: 2012年8月に再確認したところ、このバグはバージョン4.0.30319のジッターで修正されました。 しかし、v2.0.50727のジッターではまだ存在しています。 これだけ時間が経つと、古いバージョンで修正される可能性は低そうです。
関連
-
[解決済み】「The breakpoint will not currently be hit」を改善するには?このドキュメントにはシンボルが読み込まれていません。" という警告はどうすれば改善されますか?
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
[解決済み] 'SubSonic.Schema .DatabaseColumn' 型のオブジェクトをシリアライズする際に、循環参照が検出されました。
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み】Linq 構文 - 複数列の選択
-
[解決済み】Unityでゲームオブジェクトのすべての子をループスルーして破壊する方法?
-
[解決済み] .NETコンソールアプリケーションでアプリケーションのパスを取得するにはどうすればよいですか?
-
[解決済み] .NETアプリケーションを強制的に管理者として実行させるにはどうしたらいいですか?
-
[解決済み] Java JITは、JDKのコードを実行するときに不正をするのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】WebForms UnobtrusiveValidationModeは、jqueryのScriptResourceMappingを必要とする
-
[解決済み] 保護レベルによりアクセス不能になりました。
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み】URLから画像をダウンロードする方法
-
[解決済み] 関数を終了するには?
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない