2009-09-04 16 views
1

は私が追跡することはできませんよのstd ::例外Invalid_argument例外をキャッチする問題に遭遇しましキャッチすることができません。私はgcc 4.4.0(windows)、pthreads-win32 2.8.0 GC2 dllを使用しています。のstd ::例外Invalid_argument

基本的に、二つのスレッド(メインスレッドとpthread_createの使用を開始スレッド)から、Iは、ほぼ同じ時間に、クラスAのインスタンスを作成しよう。コンストラクタはstd :: invalid_argumentをスローしますが、例外を捕捉するtry/catchブロックで囲まれています。しかし、それは起こりません(非常にまれに、スレッドの1つだけが例外をキャッチする可能性があります)。

スレッドの1つのみでオブジェクトを作成しようとすると、createそれがすべきであるとして動作し、例外がキャッチされます。別の時に2つのオブジェクトを作成すると、createはうまく動作し、例外が捕捉されます。同時にそれらを作成しようとすると、:: 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

このアプリケーションは、異常な 方法でそれを終了する ランタイムを要求しました。詳細については、アプリケーションの サポートチームにお問い合わせください。

このアプリケーションは、 の方法で異常終了するようにランタイムを要求しています。詳細については、アプリケーションの サポートチームにお問い合わせください。 は、このアプリケーションはへ ランタイムを要求した再帰的

または

$ ./WOpenTest.exe

と呼ばTERMINATE 'のstd ::例外Invalid_argument' の インスタンスを投げた後に呼び出さTERMINATE珍しい方法で終了してください 方法。詳細については、アプリケーションの サポートチームにお問い合わせください。 M - 無効です!

または

$ ./WOpenTest.exe

このアプリケーションは、異常な 方法でそれを終了する ランタイムを要求しました。詳細については、アプリケーションの サポートチームにお問い合わせください。 t - 無効です!

または

このアプリケーションは、異常な 方法でそれを終了する ランタイムを要求しました。詳細については、アプリケーションの サポートチームにお問い合わせください。

このアプリケーションは、 の方法で異常終了するようにランタイムを要求しています。詳細については、アプリケーションの サポートチームにお問い合わせください。 'std :: invalid_argument'のインスタンスをスローした後にterminateが呼び出されます
what():無効です!

私は何をしなければならないと私はしていないのですか?または私はpthreadsで行方不明ですか?

+0

私は答えを見つけた、それはスレッドセーフでないMSVCRT mingwのに沸きます。 – laura

答えて

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

+0

これはしばらく前です。私はhttp://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.htmlは同じことだと思いますがそれはちょうど簡単なGoogle検索でした。 – laura

1

pthreadGC2ではなくpthreadGCE2とリンクしてみてください。

+0

私はそれをやってみた(それを言い忘れた)、何もしなかった。私が理解しているように、2つのバージョンの違いは、スレッドの終了/取り消しの処理方法です。このテストケースに違いがあるかどうかはわかりません。 – laura

1

私は何か間違って見ることはできません。

奇妙なことが起こっているかどうかを確認するためにキャッチ(...)を追加してみてください。
例外がスレッドをエスケープする場合(つまりrun())、pthreadsはアプリケーションを終了します。しかし、私はそれが起こっている場所を見ることができません。

サイドノートと同じように:
const参照で例外をキャッチしてみてください。

+0

キャッチ(...)もエスケープします。 mingw - throwing例外の問題はスレッドセーフではありません。この場合の解決策は、自分のスレッドセーフ例外を作成するようです。 – laura

2

これは、MinGWがリンクするシングルスレッドライブラリと結びついていると結論付けました。私は約configuring NetBeans to use MinGWページを発見し、それはセクション「POSIXスレッドとマルチスレッド」の下に、以下のアドバイスがあります。例外処理を使用している場合

  • 重要に:追加のコンパイラスイッチ「-mthreads」を使用してアプリケーションをコンパイルします。それ以外の場合、例外処理は信頼できず、非特定のクラッシュが発生する可能性があります。例外をDLLからアプリケーションに伝播する際に、他の問題が発生することがあります。私はネットでこれに関するいくつかのヒントを見つけましたが、DLLが例外をスローしないため、経験がありません。

また、x86のオプションのGCC documentationで説明しています: 'Mingw32' に取り扱う

-mthreads

サポートスレッドセーフ例外。スレッドセーフな例外処理に依存するコードは、すべてのコードをコンパイルして-mthreadsオプションでリンクする必要があります。コンパイル時に-mthreads-D_MTを定義します。リンク時に、特別なスレッドヘルパーライブラリ-lmingwthrdにリンクして、スレッドごとの例外処理データをクリーンアップします。

スレッドセーフの例外を作成する前に試してください。

+0

答えをありがとう。私はコンパイルして-mthreadsとリンクしています。実行時エラーはまだ現れています。しかし、 "それほど頻繁ではありません"では十分ではありませんので、今はスレッドセーフの例外を先に進めなければなりません。私は何かが不足していると思うが、すべてのgccオプションを見て、それが何であるかはわからない。 – laura

関連する問題