2010-08-14 51 views
1

有一個應用程序運行良好一段時間。突然之間,它開始在產品服務器上的某一行代碼處拋出intermitent「Object reference not set ...」錯誤。C#:晦澀對象引用錯誤

我在Visual Studio中啓動了應用程序,並在違規代碼行中用斷點進行調試,並複製了一個非常奇怪的行爲。

最初,當VS在代碼行中斷時,變量爲NULL,但如果我等待5秒左右,那麼變量不再爲NULL。這可以通過調用VS中的立即窗口中的變量來加快,這導致NULL字段立即填充或解決。這是生產服務器上錯誤的確切性質。

任何想法從哪裏開始?數據在命中該方法之前加載到變量中,但由於某些原因,在引用內存中的變量時存在延遲。開發和生產服務器上的可用內存堆。

真的很奇怪......需要幫助來找到一個地方開始解決它。

在此先感謝。

信息:.NET 3.5,VS 2008

代碼:

public static List<Model> CreateModel(List<subModelA> subModelAs, List<subModelB> subModelBs, int duration, bool isGroup) { 
      List<Model> result = new List<Model>(); 

      try { 
       if (subModelAs != null && subModelAs.Count > 0) { 
        if (subModelBs != null && subModelBs.Count > 0) { 

         subModelBs.ForEach(b => { 
          subModelA a = subModelAs.Find(x => x.id == b.comp[0].subModelAComp.subModel.id); 
          result.Add(CreateNewModel(a, b, duration)); 
         }); 
        } 
       } 
      } 
      catch (Exception ex) { 
       throw ex; 
      } 
      return result; 
     } 

下面一行是問題的根源:

subModelA a = subModelAs.Find(x => x.id == b.comp[0].subModelAComp.subModel.id); 

如果有時候b爲NULL等次subModelAComp爲NULL。如果我斷點這一行,並在即時窗口,如果我執行「b.comp [0] .subModelAComp」它是NULL,然後我執行「B」,然後再次執行「b.comp [0] .subModelAComp」,它是不再是NULL。對「b」的調用似乎強制「subModelAComp」不爲NULL。吸氣器中沒有可能導致這種改變的代碼。

***應用程序沒有線程化。沒有多線程實現****

+2

應用程序是多線程的嗎?這聽起來像是一場競賽狀況的發生,你在突破點暫停,給人口帶來時間。 – 2010-08-14 09:43:30

+2

你可以發佈代碼發生異常嗎? – Oded 2010-08-14 09:43:34

+0

歡迎來到奇妙的同步問題世界。 – erikkallen 2010-08-14 12:49:00

回答

4

沒有看到任何代碼,這是相當很難說,但兩種可能性:

  • 這是絕對是一個變量,也可能它是一個屬性?如果是屬性,則評估一次可能會給出非空值,但第二次評估可能爲空

  • 是否存在多個線程?如果是這樣,有兩個潛在的問題:

    • 如果數據是在一個線程中進行設置,但讀取另一時,「設置」線程可能寫它,但沒有「閱讀」線程讀它,因爲緩存等等。圍繞這個有多種方式 - 最簡單的就是在訪問共享數據之前始終獲取鎖。 (使用每一個訪問相同的數據塊相同的鎖。)
    • 另一個線程可以將該值設置爲空 - 所以你會看到它爲非空,再後來空

任何你可以給我們看的代碼都會有所幫助。

+0

感謝喬恩,看起來像你的第一個建議,它是屬性獲取者造成的問題,但除了標準返回,getter沒有內部邏輯。該應用程序不是線程的。 – teck 2010-08-14 12:18:15

+0

@teck:那對我來說真的沒什麼意義......你能發表任何代碼嗎? – 2010-08-14 12:23:46

+0

編輯原始帖子添加違規代碼。即時消息難倒,以前從未見過這個問題。 – teck 2010-08-14 12:47:39

1

嗯,我的第一個猜測是:

  • 是應用程序的多線程?另一個線程可以訪問變量嗎?在調試過程中,檢查「線程」調試窗口並嘗試凍結除當前線程之外的所有線程,然後查看變量內容是否仍然意外更改。

  • 它真的是一個變量嗎?或者它可能是一個具有瘋狂副作用的財產獲取者?當您從「Watch」窗口或「Immediate」窗口查詢屬性時,調試器也會觸發這些副作用。

+0

感謝您的提示。 1)該應用程序不是多線程的 2)它不是一個「實際」變量,而是屬性。但是,getter只是一個單一的返回,沒有額外的邏輯。 代碼有: varA.colB [0] .varC.varD.varE 代碼行正在訪問屬於varD的varE。然而它的varA或varC會導致NULL參考錯誤。如果代碼退出該方法,然後檢查相同的變量,則數據在變量中。我試着重建應用程序,仍然存在相同的問題。 – teck 2010-08-14 11:18:08

1

如果是屬性,請在屬性設置器上放置一個斷點,以便查看堆棧跟蹤以查看將其設置爲空的內容。

+0

響應上述線程,varA.colB [0] .varC.varD.varE 可以說當代碼處於斷點時,我在立即窗口中調用「varA.colB [0] .varC」,它是NULL 。然後我在即時窗口中調用「varA」並返回一個值,然後在立即窗口中調用「varA.colB [0] .varC」並返回值。 上面的var&col僅僅是庫存標準的實體,帶有沒有內部邏輯的getter setter屬性。 – teck 2010-08-14 11:20:56

0

任何想法從哪裏開始?數據是 加載到變量之前 命中該方法,但由於某種原因 有一個滯後引用 變量在內存中。

對我來說,這種說法聞起來很奇怪。

是否確定數據在加載到變量之前觸碰該方法?也許你沒有編寫任何多線程代碼,但是你可能會使用一些帶有異步行爲(事件等)的.NET類。我會從這個假設出發並進行調試。 (意思是,我會先在.ForEach調用之前設置斷點,或者甚至在調用CreateModel之前手動設置斷點並手動檢查列表中的每個「b」)