2012-06-23 75 views
1

解決:我從MinGW的4.6.2升級到4.7.0,它完美的作品,想這只是一個錯誤函數QueueUserAPC - 拋出異常崩潰,可能MinGW的錯誤

我開始做如何的一些研究終止正確的多線程應用程序,我發現這2個帖子(first,second)關於如何使用QueueUserAPC來通知其他線程終止。

我想我應該試試看,當我從APCProc拋出異常時,應用程序不斷崩潰。

代碼:

#include <stdio.h> 
#include <windows.h> 

class ExitException 
{ 
public: 
    char *desc; 
    DWORD exit_code; 

    ExitException(char *desc,int exit_code): desc(desc), exit_code(exit_code) 
    {} 
}; 

//I use this class to check if objects are deconstructed upon termination 
class Test 
{ 
public: 
    char *s; 

    Test(char *s): s(s) 
    { 
     printf("%s ctor\n",s); 
    } 

    ~Test() 
    { 
     printf("%s dctor\n",s); 
    } 
}; 

DWORD CALLBACK ThreadProc(void *useless) 
{ 
    try 
    { 
     Test t("thread_test"); 

     SleepEx(INFINITE,true); 

     return 0; 
    } 
    catch (ExitException &e) 
    { 
     printf("Thread exits\n%s %lu",e.desc,e.exit_code); 
     return e.exit_code; 
    } 
} 

void CALLBACK exit_apc_proc(ULONG_PTR param) 
{ 
    puts("In APCProc"); 
    ExitException e("Application exit signal!",1); 
    throw e; 

    return; 
} 

int main() 
{ 
    HANDLE thread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL); 

    Sleep(1000); 

    QueueUserAPC(exit_apc_proc,thread,0); 

    WaitForSingleObject(thread,INFINITE); 

    puts("main: bye"); 

    return 0; 
} 

我的問題是,爲什麼會發生這種情況?

我使用mingw編譯,我的操作系統是64位。

這是原因嗎?我讀過,你不應該從32位應用程序調用QueueApcProc爲一個在64位進程中運行的線程,反之亦然,但情況並非如此。

編輯:我編譯這與視覺工作室的C++編譯器2010年,它的工作完美無缺,這可能是這是gcc/mingw中的錯誤?

+0

您正在通過調用APC目標的一堆內部Windows代碼展開堆棧。如果異常處理實現是在本機Windows SEH異常之上構建的,那麼這隻能解決問題。這是MSVC,這個代碼沒有問題。不知道mingw使用什麼。它不支持捕捉SEH異常,所以它不會使用它。 –

回答

0

好問題!

我沒有mingw,但我可以用VS2005重現同樣的事情。問題是編譯器優化了catch。爲什麼?因爲根據C++標準,它是未定義的(或未指定的,或實現定義的......我不記得確切的表述),如果通過異常存在extern "C"函數會發生什麼情況。因此,編譯器假定SleepEx(這是extern "C")不會永遠扔的Test::TestTest::~Test它看到的printf不拋出任何,因此如果事情在此塊通過一個例外存在內聯後

Test t("thread_test"); 

    SleepEx(INFINITE,true); 

    return 0; 

的行爲是未定義的!

在MSVC的代碼不會在發佈版本/EHsc開關工作,但它會與/EHa/EHs,它告訴它假設C函數可能拋出的工作。也許GCC有類似的標誌。

+0

我做了一個測試,顯然對mingw異常工作沒有問題,用'extern「C」聲明的函數沒有問題,我不使用任何編譯器優化標誌 –

+0

@lazy_banana:確保嘗試將SleepEx轉換爲C++函數通過一個易失性指針間接調用。 – ybungalobill

+0

同樣的問題,這是你的意思:http://pastebin.com/Tx993PvQ? –

相關問題