2009-06-09 20 views
6

atExit関数でWSACleanupを登録することはできますか?コード内のさまざまな箇所で終了できるいくつかのアプリケーションがありますので、WSACleanupをコードを徹底して使用することは避けてください。これらすべてのアプリケーションで使用されているdllがあるので、Creatntly DllMainを使用してWSAStartup/WSACleanupを呼び出します。ただし、Microsoftでは、デッドロックの原因となる可能性があるため、DllMainを使用してWSAStartup/WSACleanupを使用することについて厳密にアドバイスしています。 WSAStarupをDllMainから移動して、Windowsソケットライブラリにアクセスする前に、すべてのアプリケーションのコードの一箇所でこれを呼び出すことができます。そして、WSAStartupを呼び出すとすぐに、atExit関数を使用してWSACleanupへの呼び出しを登録したいと考えています。誰もがこのアプローチの経験がありますか?ありがとう!WSACleanupとatExit

答えて

4

マルチスレッドアプリケーションがあり、スレッドのいくつかがまだ接続されている場合、相手側のアプリケーションは接続が終了する方法が気に入らない場合があります。ですから、main()が終了する前に順序付けられた方法ですべての通信を終了し、終了したらWSACleanupを呼び出すことができます。

1

まあ、atExitは使用しないでください。クラス内のソケットライブラリの初期化と破壊のラッピングのRAII原則に従うべきです。

+0

いいスタイルですが、これは1つのイオタを助けません。プロセスの観点から、atexit()処理はグローバルデストラクタの実行と同時に行われます。 AtExitからWSACleanupを呼び出す際に問題が発生しても、あなたは依然としてdtorからwhanを呼び出している可能性があります。 – MSalters

2

私はRAIIアプローチが好都合であることに同意します。

しかし、警告の単語:dllとハンドルが混在したatExitは、ウィンドウで壊れています。残念ながら、これはRAIIにも影響します。これは、C++ランタイムによってatExitハンドラで実装されるためです。

のatexitハンドラがウィンドウで呼び出される順序:

  1. どこかに出口が(呼ばまたはメインれる)は、プロセスで定義された
  2. のatexitハンドラが呼び出されるスコープの外に出ます。
  3. すべてのハンドルが破棄されます。
  4. dllで定義されたatexitハンドラが呼び出されます。

のDLL内のatexitハンドラは、プロセスハンドラが最初に呼び出され、DLLのハンドラが呼び出される前にハンドルが破棄されている過程でのハンドラの前に登録されている場合、それは問題ではありません。これにより、DLLによって所有されているすべてのハンドルが無効になったため、クリーンアップコードが呼び出されたときにwin32の例外が発生します。

スレッド、ミューテックス、ファイル、ソケットなどにハンドルを保持するコードです。これらがdllに割り当てられている場合は、exitを呼び出す前にクリーンナップする必要があります。

私は間違っている場合や、誰かがこれを回避する方法を知っていれば、私はこれがアプリケーションのクリーンアップに尽きない痛みを引き起こすので、私が知りたいと思っています。私は、アプリケーションが終了したときにwin32の例外を受け取った後で、これをC++ランタイムのデバッグ出口処理と考えました。

コードを終了するためにすべての呼び出しを削除する必要がありました。私は今、dllの静的データがハンドルを制御しないようにしました。すべての静的ハンドルは、メインがスコープ外になると破壊されるオブジェクトによって制御されます。

+1

壊れていません。 EXEからのグローバルdtorsの前にDLLをアンロードした場合、そのdtorから関数を呼び出すときにアプリケーションのdtorが失敗します。現在のセットアップでは、EXEはDLLに依存することができますが、逆もありません。 また、DLLMainのハンドルを開いたり閉じたりしないでください。これは新しいルールではありません。 AtExit処理はDLLMainの一部であるため、これらのルールを継承します。 すばやい解決策は、すべてのDLLリソースにスマートポインタを使用することです。アプリケーションがDLLリソースへの最後のスマートポインタをクリーンアップすると、DLLはクリーンアップ可能であり、これはAtExitの前であることを認識します。 – MSalters

+0

DLLMainのメモをありがとう、私はこれを実現しませんでした。スマートポインタ上のメモ:これはmainまたはそれ以下で宣言され、静的ではない場合にのみ有効です。 – iain

+0

私はまだそれを行う正しい方法を取得していません。特定の機能を提供するDLLを持っているとどうなりますか? DLLを読み込んで特定の関数(内部的にWinsock APIにアクセスする)を呼び出すアプリケーションでは、WSAStartupを少なくとも1回呼び出さなければなりません。これらの関数をすべてクラスにラップして、WSAStartupが少なくとも一度呼び出されるようにすることができます。アプリケーションはいつでも終了することができ、WSACleanupを呼び出す唯一の方法は、a)atExitまたはb)グローバルデストラクタを使用することです。私が理解したところでは、どちらも問題を引き起こす可能性があります。これの方法は何ですか? –

関連する問題