1

例として、呼び出し元がコールバック関数EnumWindowStations()を渡す必要がある を見てみましょう。EnumWindowStationsProc()コールバック関数は、現在のターミナル セッションのウィンドウ ステーションごとに 1 回呼び出されます。コールバック関数のシグネチャを見てみましょう。

BOOL CALLBACK EnumWindowStationProc(
    _In_ LPTSTR lpszWindowStation,
    _In_ LPARAM lParam
);

最初のパラメーターは、文字列データへのポインターです。その文字列バッファーは、コールバック呼び出し用に明示的に割り当てられましたか? また、コールバックが返された直後、または列挙関数が返される直前に解放されますか? または、文字列バッファーが割り当てられたままになり、後で使用できるように、ポインターはある種の永続メモリを指していますか?

これは重要なポイントです。永続的でない場合、たとえば、生のポインターをグローバル コンテナーに格納して、コールバックと完全な列挙プロセスが完了した後にアクセスするのは正しくないためです。代わりに、コールバックが戻る前に、基になる文字列データをアプリケーションによって制御されるバッファーにコピーする必要があります。

公式ドキュメントでは、文字列データの有効期間が明確にされていないようです。パラメータの説明には次の 1 行しかありません。

lpszWindowStation [入力]

    ウィンドウ ステーションの名前。

また、ドキュメント ページのどこにも、文字列データの有効期間については記載されていません。また、この質問に「一度だけ」、つまり Windows API でのコールバック イディオムのすべての使用について答えている MSDN ページを見つけたことを思い出すこともできません。

現時点では、EnumWindowStations()/のEnumWindowStationsProc()ケースに最も関心がありますが、回答者が一般的なケース、つまりすべての Windows API コールバック関数について想定するものに対処するのが最善です。

4

2 に答える 2

3

一般に、WINAPI によってコールバック関数に渡されるポインターは、コールバックの間のみ有効であることが保証されます (特定のコールバックのドキュメントで特に指定されていない限り)。コールバックが返されると、ポインターは無効であると見なされます (解放されるか、列挙の次の反復で上書きされる一時バッファーを指している可能性があります)。

コールバック関数は、返された後に保持する必要があるデータのコピーを作成する責任があります。上記の例の場合lpszWindowStation、コールバックが返された後に使用する必要がある場合は、独自のバッファを割り当ててから文字列をコピーする必要があります。もちろん、割り当てられたバッファの有効期間も管理する必要があります。

于 2016-08-23T21:20:02.070 に答える
3

一般に、メモリがシステムによって割り当てられている場合、コールバックの期間だけ有効であると信頼できます。それはlpszWindowStationあなたの例の場合です。コールバック関数内の文字列にアクセスしてコピーする必要があり、コールバックの外でシステムが提供するデータを参照してはなりません。

これは、ちょっとした思考実験で推測できます。コールバックが返された後にこの文字列にアクセスできた場合、いつ無効になりますか? いつ割り当てが解除されますか? あなたはそれで終わったことをシステムに伝えなければならないでしょう。それを行うように指示された API がないため、唯一の結論は上記のとおりです。

の場合は事情が異なりlParamます。その値は呼び出し時に提供されたEnumWindowStationsものであるため、実際にポインターとして使用している場合は、それが指すものの寿命を管理します。

于 2016-08-23T21:15:30.190 に答える