none
在整合開發環境內執行無問題,但直接使用執行檔會當掉,請問可能原因/該如何除錯? RRS feed

  • 一般討論

  • 各位先進好:

         小弟目前使用VS 2010 / C#開發一控制軟體,透過RS-232交換指令以控制機械設備

    在IDE中,無論是Debug或Release都沒有問題,但建置產生的執行檔,無論是Debug或Release,都在執行某項功能時會crash

    有試著把「最佳化程式碼」關閉,但情況仍沒有改善

    crash的徵狀是: 應用程式直接關閉,沒有任何錯誤訊息,沒有提示回報錯誤,偶爾會提示以偵錯工具偵錯(同樣的情況,偶爾不會提示)

    進行偵錯的話,只會告知類似「應用程式已關閉,無法進行偵錯」的訊息

    但是,若在執行檔執行後,開啟IDE並使用「工具/附加之處理序」再執行該功能,又可以正常執行

    我想這應該不是特定語言才會發生,所以post在這一區

    目前不曉得從何著手來解決這個問題,不曉得各位先進有沒有什麼好的建議或相關的經驗可以分享,謝謝大家!!

    附註: 方案架構如下

    方案 [Control Panel]
    |
    +-- C#專案,類別庫 [ADConvert] 有使用研華的DLL: ADSAPI32.DLL,但在執行會crash的該功能時,並不會使用到此DLL
    |
    +-- C#專案,類別庫 [CommunicationProtocol]
    |
    +-- C#專案,執行檔 [ControlPanel] 有使用PostSharp 2.1 Professional,已試過建置不包含PostSharp的執行檔,依然有相同問題
    |
    +-- C#專案,類別庫 [DeviceInterface]
    |
    +-- C#專案,類別庫 [IPC]
    |
    +-- C++專案,DLL [Holder] 在執行會crash的該功能時,並不會使用到此DLL
    |
    +-- MSBuild專案 [Installer]

    2012年7月3日 上午 01:47

所有回覆

  • 有確認 Crash 時的程式區塊嗎 ? 如果有的話, 把 Code 貼上來.

    另外確認一件事, 你的開發環境作業系統是 X86 還是 X64 ?


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年7月3日 上午 01:57
    版主
  • 您好:

        我的開發環境是 Win 7 x64,出貨/測試的環境是 XP x86,專案是x86

    因程序架構及多緒的關係,我不能保證以下就是全部相關的程式碼,但我把正常執行下有參與的部份盡可能貼出

    (因涉及公司開發資料,故部份程式碼需以A及B取代,請見諒)

    UI event handler:

            private void MoveUp_Click(object sender, EventArgs e)
            {
                _A.Move(A_UNIT);
                _B.Move(B_UNIT);
                _APresenter.UpdateAInfo();
            }


    Class A:

            /// <summary>
            /// Move the A by specified distance.
            /// </summary>
            /// <param name="distance">Distance to move (+: up, -: down)</param>
            /// <returns>Successful</returns>
            public bool Move(double distance)
            {
                if ((AStatus)Status != AStatus.Ready 
                    && (AStatus)Status != AStatus.Moving)
                    return false;
    
                Communication.Send(MOVE + (int)(distance * _config.Unit));
                Communication.Send(MOVING);
                ChangeStatus((int)AStatus.Moving);
                return true;
            }
            /// <summary>
            /// Get the distance of A from the bottom.
            /// </summary>
            /// <value>Distance in millimeter</value>
            public double Position
            {
                get
                {
                    _posResult = -1.0;
                    _isWaitingPos = true;
                    _t = Thread.CurrentThread;
    
                    Communication.Send(ASK_POSITION);
    
                    try
                    {
                        Thread.Sleep(this.CommunicationTimeout);
                    }
                    catch (ThreadInterruptedException) { }
    
                    _isWaitingPos = false;
    
                    if (_posResult < 0.0)
                        _posResult = _lastPos;
                    else
                        _lastPos = _posResult;
    
                    return Math.Max(_posResult / _config.Unit, 0.0);
                }
            }


    Class B:

            /// <summary>
            /// Move B by a 3D offset.
            /// </summary>
            /// <param name="offset">3D offset to move</param>
            /// <returns>Successful</returns>
            public bool Move(PointD3D offset)
            {
                if ((BStatus)Status != BStatus.Ready
                    && (BStatus)Status != BStatus.BMode
                    && (BStatus)Status != BStatus.Moving)
                    return false;
    
                string cmd = string.Format("{0}{1}{2}{3}{4}{5}{6}{7}",
                    X_MOVE, ((int)(offset.X * _config.XUnit)).ToString(), SEPARATOR,
                    Y_MOVE, ((int)(offset.Y * _config.YUnit)).ToString(), SEPARATOR,
                    Z_MOVE, ((int)(offset.Z * _config.ZUnit)).ToString());
    
                Communication.Send(cmd);
    
                //change status
                if ((BStatus)Status != BStatus.BMode)
                {
                    Communication.Send(MOVING);
                    ChangeStatus((int)BStatus.Moving);
                }
    
                return true;
            }

    Class APresenter:

            /// <summary>
            /// [Thread-Safety] Update A information on UI.
            /// </summary>
            public void UpdateAInfo()
            {
                if (_isUpdatingAInfo)
                    return;
    
                //get position of A may waste resource and cause thread waiting
                //using "_isUpdatingAInfo" flag to avoid unessesery update
                lock (this)
                {
                    _isUpdatingAInfo = true;
                    int pos = (int)_A.Position;
                    int distance = (int)_A.Range - pos;
                    
                    _UI.txtDistance.Text = distance.ToString("0");
                    _UI.txtHight.Text = pos.ToString("0");
                    _isUpdatingAInfo = false;
                }
            }

    在會crash的場合,應該是在 _APresenter.UpdateAInfo() 之前crash

    2012年7月3日 上午 02:25
  • 如果開發環境是 X64, 那很有可能問題出在某個Form的 Form.Load 事件的委派函式之中. 參考一下黑暗大的 [BUG-VS2008在x64 OS下會忽略Form_OnLoad的未處理例外], 這個現象在 VS2010 一樣存在.

    所以仔細觀察一下你自己的軟體操作步驟, 看看是在哪個 Form 開起來的時候出現 Crash.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年7月3日 上午 02:45
    版主
  • 您好:

           這個專案採用MVP架構,我們只有一個表單,而且沒有使用Form.Load

    出現crash問題點就如我程式碼中所寫,是在一個按鈕按下後,傳送2個move指令給機器,並更新UI上的資訊

    2012年7月3日 上午 03:01
  • 有跨執行緒更動 UI 的狀況嗎 ?

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年7月3日 上午 03:37
    版主
  • 您好:

          有跨執行緒更新UI,目前只用Form.CheckForIllegalCrossThreadCalls = false來規避檢查

    我遇到的這種情況有可能是因為這個原因而發生的嗎? 因為在IDE中沒有問題,所以我一直以為這樣不會有問題

    其實在該專案中,跨執行緒更新UI的部份很多,包括更新Text、變更Enable… 等,但除了會crash的那個功能之外,其他部份都沒有問題

    我先朝這個方向修改試試看,謝謝您的建議

    另外有沒有什麼方式/補助工具可以偵錯或取得crash當時的資料?


    • 已編輯 Jordan Chen 2012年7月3日 上午 06:24 補充內容
    2012年7月3日 上午 05:20
  • 您好:

        我有試著用 this.InvokeRequired 去處理

    但是當某個Thread接著進行sleep時會造成 this.Invoke() 拋出 ThreadInterruptedException

    這樣子的話,Thread原本的用途就會被破壞掉,所以我們暫時無法接著進行確認是否為跨執行緒更新UI的問題

    是否還有其他的可能性? 謝謝您

    2012年7月3日 上午 07:13
  • [Control.CheckForIllegalCrossThreadCalls 屬性 ] 只在偵錯時期有效,  也就是說, 它不應該用在正式的環境中. 在 .Net 3.5 版的時期, MSDN 文件關於此屬性的備註有一段話:

    當控制項的建立執行緒以外的執行緒嘗試存取該控制項的其中一個方法或屬性時,它通常會導致無法預期的結果。常見的無效執行緒活動為在可存取控制項的 Handle 屬性之錯誤執行緒上呼叫。將 CheckForIllegalCrossThreadCalls 設定為 true,可以在偵錯時更容易找到並診斷這種執行緒活動。請注意,如果在偵錯工具之外啟動應用程式,不當的跨執行緒呼叫總是會引發例外狀況。

    另外一個是, Thread Sleep 會拋出 ThreadInterruptedException ? 是有呼叫 Thread.Interrupt 方法 去插斷它嗎 ?

    我不清楚為什麼你們為何要暫停 Thread, 所以沒法告訴你怎麼做會比較好.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年7月3日 上午 07:25
    版主
  • 您好:

           同一個專案中幾乎每個地方都有「不當的跨執行緒存取UI」,不過目前還沒有其他會造成crash的例子

    如果真為此原因,那麼照MSDN說明,也應該會給我一個例外 (現在的情況就是因為沒有看到例外所以才難找 orz)

           另一方面是,有一條Thread負責每500毫秒就送出一系列訊息,並根據收回來的訊息變更UI (中間等待的間隔是用sleep)

    在用CheckForIllegalCrossThreadCalls = false的時候,直接變更UI沒什麼問題

    改用Invoke的時候,就會在this.Invoke()的部份出現ThreadInterruptedException  (我沒有對該Thread使用插斷)

    Invoke的具體寫法大致如下

    private delegate void TextChanger(Control ctrl, string text);
    
    public void setText(Control ctrl, string text)
    {
        if (this.InvokeRequired)
        {
            TextChangeru = new TextChanger(setText);
            this.Invoke(u, ctrl, text);
        }
        else
        {
            ctrl.Text = text;
        }
    }

    2012年7月3日 上午 07:48
  • 改用 [Control.BeginInvoke 方法] 試試看, 而且建議你採標準的寫法, Control.BeginInvoke 方法 (Delegate, Object[]) , 後面的參數以 Object 陣列傳遞

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年7月3日 上午 08:52
    版主
  • 您好:

          小弟昨天晚上使用事件檢視器查看Windows記錄時,查到crash時所留下的錯誤記錄了

    應用程式: ControlPanel.exe
    Framework 版本: v4.0.30319
    描述: 處理序已終止,因為有未處理的例外狀況。
    例外狀況資訊: System.ObjectDisposedException
    堆疊:
       於 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean ByRef)
       於 System.StubHelpers.StubHelpers.SafeHandleAddRef(System.Runtime.InteropServices.SafeHandle, Boolean ByRef)
       於 Microsoft.Win32.Win32Native.SetEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle)
       於 System.Threading.EventWaitHandle.Set()
       於 System.IO.Ports.SerialStream.AsyncFSCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
       於 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)

    看起來似乎是因為物件已經dispose所造成,但是在我相關的程式碼中並沒有主動進行dispose (也沒有使用using 區塊)

    不曉得各位先進是否能提供一些意見,謝謝~

    ※我在Stackoverflow上看到一些類似的案例,目前正在嘗試… 如果有人有解決過這個問題的話也請提供一下建議,謝謝

    • 已編輯 Jordan Chen 2012年7月4日 上午 01:45 附註
    2012年7月4日 上午 01:40
  • 我通常遇到這種問題都是 Control 已經不見了, 然後要 Inovke 去改變它.

    類似這篇文所提到的: http://www.dotblogs.com.tw/billchung/archive/2009/04/04/7851.aspx


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2012年7月4日 上午 03:18
    版主
  • 您好:

         小弟目前是暫時先用App.config的方式規避crash (我知道這不是個好方法)

    <runtime>
     <legacyUnhandledExceptionPolicy enabled="1"/>
    </runtime>

    之後另外再找時間嘗試使用第三方的序列埠 (或自己實作),看看是不是能真正的解決這個問題

    Ref: http://stackoverflow.com/questions/3808885/net-4-serial-port-objectdisposedexception-on-windows-7-only

    這篇文章中有提到類似的問題,以及有人提出可能可以解決的第三方函式庫,供有需有的人作參考~

    2012年7月4日 上午 07:55
  • 我有碰過 USB to 232 的 driver 有問題時, .Net 2.0 寫的程式會被當在裡面~

    你試看看有實體通訊埠的是否正常。


    T.L. Cheng

    2012年7月14日 上午 09:35
    版主
  • 您好:

            我們的軟體是直接使用RS-232,另外也有試過使用Eltima Virtual Serial Port Driver,兩者皆有相同的問題

    2012年7月16日 上午 09:27
  • 你試試看把 DEP 關掉試試。

    我有碰過類似這篇的問題,也是 DEP 造成:

    [OWC] 關於 8 月份安全更新中的 11.0.8304.0

    如果關掉 DEP 正常,可能是 該 DLL 或 COM 元件記憶體處理得不好。

    這篇也是 IDE 正常,執行檔不正常的案例:

    MAPI 與 AmosConnect 間的記憶體存取錯誤


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2012年7月16日 下午 03:01
  • 您好:

          謝謝您的建議,我們目前無論是XP或是WIN7上,都是設定成「僅為基本的Windows程式和服務開啟DEP」

    您的意思是,把硬體的DEP全部都關掉試試看嗎?

          另外,我們沒有使用第三方的DLL或COM元件,全部都是.NET Framework 4.0中的元件

    包括可能是問題點的System.IO.Ports.SerialPort

    2012年7月17日 上午 09:04
  • 你的rs-232 prot是電腦內建的還是用usb轉rs232,如果是可能要確認一下該usb轉rs232的轉接線的chip是經過ms認證過的,不然可能會有問題,我之前就遇到這樣的問題, rs232會無緣無故沒有反應,後來換了一條轉接線就好了~~

    夢想無限 飛翔在天際精靈

    2012年7月17日 上午 10:00
  • 前面不是說用了研華的 DLL 嗎?

    硬體 DEP 關閉可從 BIOS 關,比較省事。

    只用 SerialPort 的話,我碰過在 Win7 x64 上,配上通訊埠監控軟體的 driver 時,可能直接就變成 BSOD ...


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2012年7月17日 下午 12:35
  • 您好:

         噢,是的,不過也如同我在最上面所說明,在會crash的功能上沒有使用到該DLL

    事實上,為了測試用,我也有另外寫一個Dummy ADConvert,不會使用到任何DLL

    而相同的錯誤仍然會繼續發生

         另外,我看過測試/出貨用的機器,是不具備硬體DEP的,不過相同的錯誤仍會發生在該機器上

    2012年7月18日 上午 01:57