2017-10-20 64 views
9

我有一些代碼在發佈版本和調試版本之間的行爲不同。它在Debug中正確運行,但在Release中不正確。爲什麼此程序在發佈版本中輸入if塊但不在調試版本中?

我有一個函數返回ReadOnlyCollection<MyCustomClass>。一個部分是這樣的:

 var result = new List<MyCustomClass>(); 
     ... 
     var list1 = this.returnEmptyList(); 
     var list2 = this.returnListWithOneItem(); 
     if (list1.Count == 0 && list2.Count == 0) 
     { 
      functionOutVariable = string.Empty; 
      return result.AsReadOnly(); 
     } 

對於我已經簡化了代碼,並命名爲一種通用的方式變量排除故障的目的,方法和returnEmptyListreturnListWithOneItem如下所示:顯然

private List<string> returnEmptyList() 
    { 
     return new List<string>(); 
    } 

    private List<string> returnListWithOneItem() 
    { 
     return new List<string> {"something"}; 
    } 

它不應該進入if塊,因爲list2.Count應始終爲1,但是當我在一個發佈版本執行此,它確實

enter image description here

因此,有明確一些優化回事,因爲你可以看到,list1不可訪問,並通過它加強在執行管線416,然後立即躍升至行421,我應該說,在我的解決方案使用的所有組件。 NET框架4.6.2,並且我正在運行Visual Studio 2017版本15.3.5。

當我改變構建調試和執行這一點,執行管線416,417,和上線418它顯示list1.Count是0和list2.Count爲1,它正確地做進入if塊。

我試圖做一個測試項目來重現這一點,但我不能。我正在尋找任何方式來達到此目的。我不只是想要一個讓它消失的修復程序 - 我需要明白我做錯了什麼。

+1

這聽起來像編譯器中的錯誤。你能在每個版本中發佈編譯後的IL嗎? – SLaks

+1

在** Release **模式下進行調試可能會產生問題:當前語句指針可能不準確,並且如果您已啓用** Optimize Code **,則可能會優化變量。轉到項目屬性並檢查** Build **選項卡下。如果需要禁用,您可能需要在完成後再次啓用它。 –

+1

如果未輸入「if」程序段,那麼稍後在此功能中會做什麼? – Evk

回答

7

好吧,我敢肯定,這是我的函數的其餘部分中的一個微妙的錯誤的結果,它允許編譯器只是優化了if塊並提前返回。我可以重現這個測試項目調試器的行爲,它完全是有道理的在這種情況下:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test = new MyClass(); 
     test.DoTest(out var result); 
     Console.WriteLine(result); 
     Console.ReadKey(); 
    } 
} 

class MyClass 
{ 
    public ReadOnlyCollection<MyCustomClass> DoTest(out string functionOutVariable) 
    { 
     var result = new List<MyCustomClass>(); 
     var list1 = this.returnEmptyList(); 
     var list2 = this.returnListWithOneItem(); 
     if (list1.Count == 0 && list2.Count == 0) 
     { 
      functionOutVariable = string.Empty; 
      return result.AsReadOnly(); 
     } 
     functionOutVariable = string.Empty; 
     return result.AsReadOnly(); 
    } 

    private List<string> returnEmptyList() 
    { 
     return new List<string>(); 
    } 

    private List<string> returnListWithOneItem() 
    { 
     return new List<string> { "something" }; 
    } 
} 

class MyCustomClass 
{ 

} 

當我在一個發佈版本與調試器中執行,這似乎進入if塊,但在現實中,它只是優化了if塊完全和調試器混淆性表明它執行的,而不是跳過它if塊內的線路:

enter image description here

編輯:我已經CONF因爲編譯器優化,在引發我的問題的函數中出現了一個錯誤,並且查看Release構建代碼時調試器的行爲只是讓我感到困惑。

要清楚,我的問題是不正確的:該函數實際上在發佈和調試版本中給出了相同的結果,但我錯了。這是因爲我遵循這個(有缺陷的)序列:

  1. 我有一個失敗的測試(對發佈版本)。
  2. 我用調試器(仍在Release版本中)運行測試,看到它顯然錯誤地進入if塊。
  3. 然後,我將構建版本切換到Debug,並使用調試器運行測試,並看到它跨越了if塊。 我認爲(不正確)這是我的問題的來源。

這給了我上面看到的野鵝追逐。對不起浪費你的時間,但我當然發現練習內容豐富。也許別人會在未來從我的錯誤中吸取教訓。 :)

相關問題