私は最近多くのC#/。Netコードに取り組んでいて、何か(潜在的に)奇妙なことに気づきました。
私が所属しているチームは、Windows7ProfessionalとVisualStudio2008を使用して開発しており(その価値があるため)、生成されたコードの一部が異なるバージョンのWindows(私の例では、.Net3.5がインストールされたWindowsXP Professional)で実行されている場合)少し奇妙な動作が発生します。
私が気付いたのは、スイッチブロック内のネストされたifの非常に特定のセット(それぞれが同じメソッドを呼び出しますが、パラメーターが異なる)は、特定の1台のマシンでの実行時と開発時の動作が異なるようです。マシン。私が意味する例はこれです:
switch (someVariable)
{
case true:
//do some stuff
//this case seems fine when stepped through
break;
case false:
//do some stuff
//this is the case that causes problems
if (Foo())
{
if(Bar())
{
someOtherMethod();
//I'll call these the nested ifs
if (object.SomeValue == targetValueOne)
FooBar(string, someParam, int anotherParam);
if (object.SomeValue == targetValueTwo)
FooBar(string differentStrParam, int differentIntParam);
else
FooBar(string thirdStrParam, int thirdIntParam);
}
}
else
{
//do some different things
}
break;
}
この例は非常に複雑ですが、目の前にあるコードにも(ほぼ)当てはまります(object.SomeValueの値をチェックする場合は余分なものがあります)。
Windows 7(開発)マシンでは、コードは完全に実行されます-object.SomeValueの順列ごとにコードをステップ実行し、各コードパスは計画どおりに実行されます。ただし、このコードをWindows XP(テスターに属する)マシンで実行すると、ネストされたifは呼び出されないように見えます。特に、Bar()がtrueを返した場合はそうです。
FooBar()には2つのバージョンがあり、1つは戻るバージョンと、もう1つは返さないバージョンです。ここでは、そうでないバージョンを明示的に呼び出しています。
Foo()とBar()は2つの異なるセットアップメソッドであり、セットアップ手順を完了するとtrueを返し、そうでない場合はfalseを返します。
上で述べたように、このコードがテスターのマシンで実行されると、ネストされたifは完全にスキップされます。それらは開発マシンで正しく評価されますが。JITは実行時にネイティブコードにコンパイルされ、ネイティブコードはそれが実行されているマシンに固有であることを私は知っています。
それで、テスターのマシン上のJITである可能性があるかどうか、これらのネストされたifがスキップされる原因であるかどうか、または何かを見逃したかどうかを誰かが知っているかどうかを尋ねていると思います。または、JITコンパイラがこのブロックを最適化して、想定どおりに実際に実行されないコードを生成しようとしている可能性がありますか?
おそらくより明確な例:
switch (Hawrdware.SomeProperty)
{
case true:
//do some stuff
//this case seems fine when stepped through
break;
case false:
//do some stuff
//this is the case that causes problems
if (SetupHardware()) //calls our library functions
{ //these have been tested thoroughly
if(WaitForCorrectResponse()) //waits for the correct post-setup
{ //message from the hardware
SendOTAMessageFromHardware(string message);
//I'll call these the nested ifs
if (Hawrdware.PropertyOne == targetValueOne)
SendOTAMessageFromHardware(string message, int timeOutForResponse);
if (Hawrdware.PropertyTwo == targetValueTwo)
SendOTAMessageFromHardware(string message, int timeOutForResponse);
else
SendOTAMessageFromHardware(string message, int timeOutResposnse);
}
}
else
{
//do some different things
}
break;
}
public void SendOTAMessage(string message)
{
if (message != null)
{
device.Write(message);
//Hardware's on-board OS takes care of the rest
}
}
public void SendOTAMessage(string message, int TimeOut)
{
if (message != null)
{
StopWatch clock = new StopWatch();
device.Write(message);
//Hardware's on-board OS takes care of the rest
while (time.Elapsed.TotalSeconds < TimeOut)
{
//wait and see if we get a response
//if we do, store it in a string (legacy
//reasons state we have to do this
}
}
}
public string SendOTAMessage(string message, int TimeOut)
{
if (message != null)
{
StopWatch clock = new StopWatch();
device.Write(message);
//Hardware's on-board OS takes care of the rest
while (time.Elapsed.TotalSeconds < TimeOut)
{
//wait and see if we get a response
//if we do, return this message as a string
}
}
}