2009-09-04 90 views
1

我碰到一個醒目的std :: invalid_argument不同的是,我不能追蹤的問題。我使用的是gcc 4.4.0(windows),pthreads-win32 2.8.0 GC2 dll。無法趕上的std :: invalid_argument

基本上,從兩個線程(主線程和線程開始使用在pthread_create),我嘗試在大致相同的時間來創建一個類的實例。構造函數拋出一個std :: invalid_argument,但它被try/catch塊包圍,它應該捕獲異常。但是,這並沒有發生(很少,只有其中一個線程可能會發現異常 - 沒有關於哪個會執行的規則)

如果我只嘗試在其中一個線程上創建對象,則創建按原樣工作,並發現異常。如果我在不同的時間創建這兩個對象,則該創建將按其應有的方式工作,並捕獲異常。如果我嘗試同時創建它們,:: terminate()會被調用。

也許有人有爲什麼會這樣的想法(我已經排除頭):

void *run(void *ptr) 
{ 
    Sleep(5000); 
    try 
    { 
     A *a = new A(5); 
     a->a = 12; 
    } 
    catch (std::exception &ex) 
    { 
     printf("t - %s\n", ex.what()); 
    } 
    return NULL; 
} 

int main(void) { 
    pthread_t t; 
    if (pthread_create(&t, NULL, run, NULL) != 0) 
    { 
     printf("No thread\n"); 
    } 
    else 
    { 
     Sleep(5000); 
     try 
     { 
      A *a = new A(5); 
      a->a = 13; 
     } catch (std::exception &ex) 
     { 
      printf("M - %s\n", ex.what()); 
     } 
     pthread_join(t, NULL); 
    } 
    return 0; 
} 

class A 
{ 
public: 
    A(int a); 
    virtual ~A(); 
    int a; 
}; 
A::A(int a) 
{ 
    throw std::invalid_argument("Invalid!"); 
} 
A::~A(){} 

生成文件是:

CXXFLAGS = -O0 -g -Wall -Werror -fmessage-length=0 
OBJS = WOpenTest.o A.o 
INCL = -I../pthreads-win32/include 
LIBS = -lws2_32 -lgdi32 -lpthreadGC2 
LIB_DIRS = -L ../pthreads-win32/lib 
TARGET = WOpenTest.exe 
$(TARGET): $(OBJS) 
$(CXX) -o $(TARGET) $(OBJS) $(LIBS) $(LIB_DIRS) $(INCL) 
WOpenTest.o : WOpenTest.cpp 
g++ $(CXXFLAGS) -c WOpenTest.cpp $(INCL) 
A.o : A.cpp A.h 
g++ $(CXXFLAGS) -c A.cpp $(INCL) 
all: $(TARGET) 
clean: 
rm -f $(OBJS) $(TARGET) 

我看到輸出:

(最常見)$ ./WOpenTest.exe

此應用程序已請求 運行時終止它在一個不尋常的方式 。請聯繫應用程序的 支持團隊以獲取更多信息。

此應用程序請求 運行時終止它在一個不尋常的 方式。請聯繫應用程序的 支持團隊以獲取更多信息。 終止拋 '的std :: invalid_argument' 的 實例 終止遞歸調用

$ ./WOpenTest.exe

此應用程序已請求 運行後叫終止它在一個不尋常的 方式。請聯繫應用程序的 支持團隊以獲取更多信息。 M - 無效!

$ ./WOpenTest.exe

此應用程序已請求 運行時終止它在一個不尋常的方式 。請聯繫應用程序的 支持團隊以獲取更多信息。 t - 無效!

此應用程序已請求 運行時終止它在一個不尋常的方式 。請聯繫應用程序的 支持團隊以獲取更多信息。

此應用程序請求 運行時終止它在一個不尋常的 方式。請聯繫應用程序的 支持團隊以獲取更多信息。 終止調用後拋出一個 實例'std :: invalid_argument'
什麼():無效!

任何想法,我應該做什麼,我不是?或者我錯過了pthreads?

+0

我已經找到了答案,把它歸結爲MinGW的MSVCRT不是線程安全的。 – laura 2009-09-04 10:09:10

回答

2

在這裏發佈最終答案,以防有人在未來尋找它。問題是在GCC 4.4重大錯誤:

http://n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-thread-specifier-not-working-td3440749.html

+0

看起來這個鏈接不再有效。出於好奇,libstdC++如何鏈接到您的應用程序中?它是靜態還是動態完成的? 我遇到了與mingw-gcc4.5.2類似的問題,但前提是我要動態鏈接到libstdC++ 6.dll – greatwolf 2011-06-02 10:23:12

+0

這是前一陣子。我認爲http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html是同樣的事情,但這只是一個快速的谷歌搜索。 – laura 2011-07-25 15:38:40

1

嘗試使用pthreadGCE2而不是pthreadGC2進行鏈接。

+0

我試過這樣做(忘記提及它),它什麼也沒做。據我所知,兩個版本之間的區別是它們如何處理線程退出/取消 - 我不知道它是否會對此測試用例產生影響 – laura 2009-09-04 08:53:37

1

我看不到任何錯誤。

嘗試添加一個catch(...)來查看是否有其他奇怪的事情發生。
如果異常轉義線程(即run()),則pthreads將終止應用程序。但我看不到發生了什麼。

正如旁註:
嘗試通過const引用捕獲異常。

+0

它也會逃避catch(...),因爲有一個mingw問題 - 拋出異常不是線程安全的。在這種情況下,解決方案似乎在編寫我自己的線程安全異常。 – laura 2009-09-04 13:07:43

2

您已經斷定這與MinGW鏈接到的單線程庫相關聯。我發現了一個網頁約configuring NetBeans to use MinGW,它有下以下建議「多線程使用POSIX線程」部分:

  • 重要,如果使用異常處理:編譯與附加的編譯器開關「-mthreads」您的應用程序。否則,異常處理將無法正常工作,並且可能會發生非特定的崩潰。將異常從DLL傳播到應用程序時可能會出現其他問題。我在網上發現了一些關於這個的提示,但沒有經驗,因爲我的DLL不會拋出異常。

它在GCC documentation還描述了x86的選項:

-mthreads

支持線程安全的異常處理上 'Mingw32'。依賴線程安全異常處理的代碼必須將所有代碼編譯並鏈接到-mthreads選項。編譯時,-mthreads定義-D_MT;鏈接時,鏈接在特殊線程助手庫-lmingwthrd中,它清理每個線程的異常處理數據。

請在嘗試編寫自己的線程安全異常之前嘗試一下。

+0

感謝您的回答。我編譯並鏈接了-mthreads:運行時錯誤仍然出現,雖然不像以前那麼頻繁。但是,「不經常」不夠好,所以現在我必須繼續使用線程安全的異常。我想我錯過了一些東西,但看了所有的海灣合作委員會的選項後,我無法確定那是什麼 – laura 2009-09-07 07:01:54