我最近一直在处理很多 C#/.Net 代码,并注意到一些(可能)奇怪的东西。
我所在的团队正在使用 Windows 7 Professional 和 Visual Studio 2008(物有所值)进行开发,并且当生成的某些代码在不同版本的 Windows 上运行时(在我的示例中,安装了 .Net 3.5 的 Windows XP Professional ) 我们得到一些稍微奇怪的行为。
我注意到的是一组非常具体的嵌套 ifs(每个都调用相同的方法,但使用不同的参数),在 switch 块中,在一台特定机器上运行时的行为似乎与开发时不同机器。我的意思的一个例子是这样的:
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;
}
这个例子过于复杂,但它仍然(几乎)适用于我面前的代码(有额外的 if 来检查 object.SomeValue 的值)。
在 Windows 7(开发)机器上,代码运行完美——我已经通过 object.SomeValue 的每个排列逐步完成它,并且每个代码路径都按计划执行。但是,当此代码在 Windows XP(属于测试仪)机器上运行时,嵌套的 if 似乎甚至没有被调用,尤其是当 Bar() 返回 true 时。
FooBar() 有两个版本,一个返回,一个不返回。我在这里明确调用了没有的版本。
Foo() 和 Bar() 是两种不同的设置方法,如果它们完成设置步骤则返回 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
}
}
}