【发布时间】:2012-04-04 08:19:27
【问题描述】:
我最近一直在编写大量 C#/.Net 代码,并发现了一些(可能)奇怪的东西。
我所在的团队正在使用 Windows 7 Professional 和 Visual Studio 2008(物有所值)进行开发,并且当生成的某些代码在不同版本的 Windows 上运行时(在我的示例中,Windows XP Professional 和 . Net 3.5)我们得到了一些稍微奇怪的行为。
我注意到的是一组非常具体的嵌套 if(每个都调用相同的方法,但使用不同的参数),在 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
}
}
}
【问题讨论】:
-
JITter 编译 to native 代码 from 字节码 (CIL)。此外,对于您的最后一句话 - 如果我们要提供帮助,您可能需要想出一个(最小的)示例,您可以向我们展示。
-
我想你可能在这里叫错了树。您是否在 XP 和 Win7 上针对相同的框架版本进行编译?你有不同的 Win7 机器来测试吗?在 Foo 或 Bar 中是否可以访问任何特定环境?
-
可能是 3.5 运行时中的 JIT 错误,已在 4.0 运行时中修复。我怀疑这与操作系统的选择无关。另一个问题是,您不能从逐步完成没有达到某事,即它没有被执行得出结论。可能是调试器问题。
-
@Slugart: Foo 将特定的设置命令发送到一个附加的硬件,Bar 进入一个循环,直到设备以正确的响应响应这些设置命令(或直到某个时间- out 已到达)。两者都使用我们的自定义库与硬件进行通信。 AFAIK,我们也都使用与测试人员机器相同版本的框架。开发机器与测试机器的唯一(主要)区别是操作系统版本——除了机器的底层硬件。这会导致问题吗?
-
这很可能是操作系统与硬件接口的问题或逻辑问题。尝试在 Win7 上构建并在 XP 上运行;)正如 AakashM 提到的,JITter 编译为本机代码。
标签: .net compilation c#-3.0 jit