2013-08-28 177 views
3

我的一個程序中有一個奇怪的競爭條件,導致它只在發佈模式和OUTSIDE visual studio環境中崩潰。如何調試在發佈版本中發生的崩潰只

如果我使用F5(無論是發行版還是調試版)在Visual Studio中以發佈模式啓動此過程,它就會起作用。

如果我使用調試信息創建發佈副本,它不會崩潰。

我想知道如何調試這樣的問題..爲什麼它不在視覺工作室內崩潰?即使啓動發佈版本,Visual Studio是否會減慢可執行文件的速度?

+3

聽起來像在某些時候,你正在調用未定義的行爲 – nijansen

+0

我甚至不知道這個問題,因爲我無法調試它,並且應用程序的代碼太大而無法在此處發佈 –

+0

當您調用UB時,可能會發生,包括你觀察到的。有無數的方法來調用UB,其中沒有人會願意在這裏開始列出它們。 – PlasmaHH

回答

2

問題是如何在不改變導致崩潰的運行時行爲的情況下調試應用程序。答案是更好的驗屍診斷

你可以改進你的異常處理代碼,如果這是一個生產應用程序,你應該。

  1. 安裝使用std::set_terminate

    如果你想在本地調試這個問題自定義終止處理程序,您可以運行終止處理和輸出一些文本內的無限循環到控制檯,通知您std::terminate有被稱爲。然後附加調試器並檢查調用堆棧。

    在生產應用程序中,您可能希望將錯誤報告發送回家,理想情況下還有一個允許您分析問題的小內存轉儲。

  2. Microsoft擁有一個結構化的異常處理機制,可以讓您捕獲硬件和軟件異常。 See MSDN。您可以使用SEH保護部分代碼,並使用與1)中相同的方法來調試問題。 SEH提供了有關從生產應用程序發送錯誤報告時可以使用的異常的更多信息。

如果它確實是一個競爭條件,然後在正確的時間是至關重要的,我想,在安裝調試器,即使在發行模式不改變的行爲,因此定時

1

這回答「有什麼不同」,但可能不是您的代碼在發佈模式中存在爭用條件的完整答案。

當你移動到VS之外的版本時,有一件事就是運行時正在使用堆。就我所知,它甚至在釋放模式下也使用VS中的調試堆。

由於定義的堆分配必須被鎖定,因此使用調試堆(在給予客戶端代碼之前填充內存,並在釋放內存時再次填充內存)會更頻繁地阻止競爭線程(導致更多順序執行),所以你可能會發現這是比賽發生的原因之一。

如果您在調試環境(配置 - >調試 - >環境變量...)中設置環境變量_NO_DEBUG_HEAP=1,那麼您將在調試器中得到相同的結果。

不幸的是,這些東西調試起來可能非常棘手。有一件事我發現有用的是爲「我去過的地方」(數組越簡單,越好 - 如此整數值或小字符串或某物)存​​儲一組值,而不是每次都打印一些東西。如果您可以停止在調試器中或以某種方式檢測到崩潰,那麼可以轉儲「跟蹤」,然後查看您現在的位置以及涉及的線程。

1

F5之間的主要區別在Visual Studio中,單獨運行一個程序是當程序最初在調試器下運行時,Windows在特殊的調試堆上運行該程序。調試堆與普通堆不同,在某些情況下,這可能會導致只在普通堆上出現錯誤。

你可以運行程序,然後附加調試器,然後它會使用普通的堆,你的bug應該愉快地重現。爲防止程序在連接調試器之前「過度」,您可以在入口點內插入一個調用函數Sleep()函數。

相關問題