【问题标题】:C#/.Net JIT on difference versions of WindowsC#/.Net JIT 在不同版本的 Windows 上
【发布时间】: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


【解决方案1】:

你需要排除所有其他可能的因素,除非你有比“我的 if 语句永远不会在调试器中被命中”更确定的东西。

构建两台相同的机器:

  • 一个使用“可疑”操作系统版本,另一个使用 Dev 中的版本。两者都应该在初始测试中使用相同的“位数”——即如果一个是 32 位,另一个也必须是 32 位。
  • 确保新机器具有正确的 .NET Framework 版本、第三方库、所需软件等。
  • 确保已从 Windows 更新修补它们。
  • 确保已安装外部硬件驱动程序,并且都是相同版本的驱动程序。如果硬件供应商根据操作系统提供不同的库/软件,那么您需要知道原因。
  • 确保外部硬件连接正确,两者的软件版本相同。
  • 确保外部硬件连接相同。 (机器上的相同端口)
  • 确保外部硬件在两者上发回相同的响应(外部硬件的行为可能因操作系统版本而异)
  • 确保在相同的线程上以相同的顺序触发相同的事件。
  • 确保在输入方法时将相同的变量设置为相同的状态。

在整个测试过程中,请确保您对其中一个执行的每个操作都与另一个执行相同。

【讨论】:

    【解决方案2】:

    如果您确实怀疑编译错误,请执行以下操作:

    1. 在切换前跟踪 Hawrdware.SomeProperty 的值
    2. 在 false 开关盒内添加跟踪
    3. 在 SetupHardware 和 WaitForCorrectResponse 中添加跟踪值。

    如果您在 case 语句中看到 Hardware.SomeProperty==false + trace 但在方法中看到 no trace 可能是正确的。也不需要单步执行,从等式中删除调试器只会让事情变得更简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 2018-01-19
      相关资源
      最近更新 更多