0

これによると

「ただし、スレッドが を呼び出す場合pthread_exit、C++ は、スレッドのスタック上のすべての自動変数に対してデストラクタが呼び出されることを保証しません。この機能を回復する賢い方法は、特別な例外をスローして、スレッド関数のトップ レベルで pthread_exit を呼び出すことです。 "。

これに続いて、この付随するコードが続きます

class ThreadExitException
{

public:
ThreadExitException (void* return_value)
                    : thread_return_value_ (return_value) { }

void* DoThreadExit ()
{
 pthread_exit (thread_return_value_);
}

private:
void* thread_return_value_;

};

void do_some_work ()
{
while (1) 
{
 /* Do some useful things here...*/
 if (should_exit_thread_immediately ())
 throw ThreadExitException (/* thread’s return value = */ NULL);
}
}

void* thread_function (void*)
{
 try 
 {
  do_some_work ();
 }
catch (ThreadExitException ex) 
{
 ex.DoThreadExit ();
}

return NULL;
}

私が理解していることから... pthread_exit が呼び出された場合、スタックのすべての自動変数のデストラクタが呼び出されない可能性があります。そのため、例外処理を使用して、すべての変数に対して確実にデストラクタが呼び出されるようにします。(説明から引用: 「pthread_exit を直接呼び出す代わりに ThreadExitException をスローすることにより、例外はトップレベルのスレッド関数でキャッチされ、スレッドのスタック上のすべてのローカル変数は、例外が浸透するにつれて適切に破棄されます。」

のマニュアルページによるとpthread_exit

「まだポップされていない pthread_cleanup_push(3) によって確立されたすべてのクリーンアップ ハンドラは、(プッシュされた順序の逆で) ポップされ、実行されます。 スレッドにスレッド固有のデータがある場合、その後、クリーンアップ ハンドラが実行され、対応するデストラクタ関数が不特定の順序で呼び出されます。

これは、デストラクタが関数に対して呼び出されることを示しているため、自動変数は解放されますか?. では、コードで示されているように、なぜ例外処理を使用する必要があるのでしょうか?

4

2 に答える 2

3

スレッド固有のデータは、あなたが理解しているものとは異なります。スレッド固有のデータは、各スレッドがグローバルデータの個別のコピーを取得するように設定されたグローバル データです。したがって、スレッド固有のデータは、想定どおりにスタックに存在しません。

詳細については、こちら(および pthread の例) を参照してください。

于 2013-03-29T08:47:57.163 に答える
1

いいえ、スレッド固有のデータに対してデストラクタ関数が呼び出されると書かれています。これは、スレッド コール スタック内の自動変数で呼び出される C++ デストラクタとはまったく異なります。

man pthread_key_createスレッド固有のデータに関連付けられたデストラクタ関数のドキュメントについては、を参照してください。

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));

[...] オプションのデストラクタ関数を各キー値に関連付けることができます。スレッドの終了時に、キー値に NULL 以外のデストラクタ ポインタがあり、スレッドがそのキーに関連付けられた NULL 以外の値を持っている場合、キーの値は NULL に設定され、ポイントされている関数が呼び出されます。唯一の引数として以前に関連付けられた値。スレッドの終了時に複数のデストラクタが存在する場合、デストラクタ呼び出しの順序は指定されていません。[...]

于 2013-03-29T08:49:13.513 に答える