0

我最近一直在处理很多 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
    }
  }
}
4

2 回答 2

0

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

构建两台相同的机器:

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

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

于 2012-04-04T08:51:48.880 回答
0

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

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

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

于 2012-04-04T09:12:38.057 回答