2013-12-11 31 views

回答

2

我到目前爲止發現的唯一辦法是包裝每一個線程的執行與應用:

__try 
{ 
    // Call the thread start function here 
} 
__except(MyExceptionFilter(GetExceptionInformation()) 
{ 
    // Handle the exception here 
} 

這聽起來像一個大量的工作,但如果你寫一個由相對容易函數封裝了線程你是這樣的:

typedef struct { 
    void* startFct; 
    void* args; 
} ThreadHookArgs; 

// "params" contains an heap-allocated instance of ThreadHookArgs 
// with the wrapped thread start function and its arguments. 
DWORD WINAPI wrapThread(LPVOID params) { 

    ThreadHookArgs threadParams; 
    memcpy(&args, params, sizeof(ThreadHookArgs)); 

    // Delete the parameters, now we have a copy of them 
    delete params; 

    __try { 
     // Execute the thread start function 
     return ((LPTHREAD_START_ROUTINE) threadParams.startFct) (threadParams.args); 
    } 
    __except(MyExceptionFilter(GetExceptionInformation()) 
    { 
     // Handle the exception here 
     return EXIT_FAILURE; 
    } 

} 

然後編寫調用掛鉤,而不是線程啓動功能自己線程創建函數:

// Drop-in replacement for CreateThread(), executes the given 
// start function in a SEH exception handler 
HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, 
         DWORD dwStackSize, 
         LPTHREAD_START_ROUTINE lpStartAddress, 
         LPVOID lpParameter, 
         DWORD dwCreationFlags, 
         LPDWORD lpThreadId) 
{ 
    HANDLE hThread; 
    DWORD dwThreadId; 

    LPTHREAD_START_ROUTINE startFct = lpStartAddress; 
    LPVOID startParam = lpParameter; 

    // Allocate the hook function arguments on the heap. 
    // The function will delete them when it runs. 
    ThreadHookArgs* hookArgs = new ThreadHookArgs; 
    hookArgs->fct = lpStartAddress; 
    hookArgs->args = lpParameter; 

    // Set the start function of the created thread to 
    // our exception handler hook function 
    startFct = (LPTHREAD_START_ROUTINE) &wrapThread; 
    startParam = hookArgs; 

    // Start the hook function, which will in turn execute 
    // the desired thread start function 
    hThread = CreateThread(lpThreadAttributes, 
          dwStackSize, 
          startFct, 
          startParam, 
          dwCreationFlags, 
          &dwThreadId); 

    return hThread; 
} 

請注意,如果您使用的是Windows CE 6.0及更高版本,這些版本的向量異常處理,這可能使它更容易:

http://msdn.microsoft.com/en-us/library/ee488606%28v=winembedded.60%29.aspx

+1

向量異常處理不解決這個問題,因爲向量在調用任何幀特定的過濾器之前調用異常過濾器,而在調用所有異常過濾器之後調用未處理的異常過濾器。這是非常容易出錯的,因爲它使許多假設在其他假設之前被調用。 –

+1

此解決方案的另一個問題。如果您完全不尊重Windows CE ABI,那麼可能會跳過基於幀的異常過濾器,因爲內核可能無法正確展開堆棧。請注意,即使程序不尊重Windows CE ABI,矢量異常過濾器仍然會被調用。 –

+1

好點。事實上,我只使用向量化異常處理來捕獲STATUS_CRASH_DUMP,並繞過在這種情況下得到的錯誤窗口,而是傾倒關於觸發它的異常的日誌;我也沒有意識到ABI問題,迄今爲止解決方案工作得很好。可悲的是,似乎沒有真正普遍的辦法來解決這個問題。 –