C28615

警告 C28615: __try ブロックで _alloca を呼び出す際には、__except() ブロック内で _resetstkoflw を呼び出す必要があります。 catch() ブロック内から _resetstkoflw を呼び出さないでください

アプリケーションが catch ブロック内で _resetstkoflw 関数を呼び出した場合、またはアプリケーションが except ブロック内で _resetstkoflw を呼び出さずに try ブロック内で alloca を呼び出した場合に、コード分析ツールによってこの警告が報告されます。

各例外の後に (_resetstkoflw などによって) スタックが修正されない限り、スレッドがキャッチできるスタック オーバーフロー例外 (_alloca の呼び出しから発生) は 1 つのみです。 _alloca から最初の例外が発生した後にスタックが修正されていない状態で 2 つ目の例外が発生すると、プロセスは直ちにサイレントで終了します。

現在のスタック ポインターが、スタック上の 3 ページ目を超えるアドレスを指している場合は、_resetstkoflw を呼び出す必要があります。 これは、スタック ポインターが指している (または間もなく指す) 現在のページからガード ページを作成することが意味を成さないためです。

_resetstkoflw 関数は、構造化例外ハンドラー フィルター式から、または構造化例外ハンドラー フィルター式で呼び出される関数から呼び出さないでください。

次の例では、スタック アンワインドが発生する前にフィルター式が呼び出されるため、コード分析ツールによってこの警告が報告されます。 スタック オーバーフローが発生すると、現在のスタック ポインターがスタックの下から 3 番目のページを指しているときにフィルター式が呼び出されます。

__try 
{
    /* The following could cause stack overflow */
    char *x = _alloca (i);
}
__except ((GetExceptionCode () == EXCEPTION_STACK_OVERFLOW) 
    ? (_resetstkoflw (), EXCEPTION_EXECUTE_HANDLER) 
    : EXCEPTION_CONTINUE_SEARCH)
{
}

次の例でも同様の理由でエラーになります。


__try 
{
 char *x = _alloca (i);
}
__except (SEHFilter (GetExceptionCode ()))
{
}

int SEHFilter (DWORD dwExceptionCode)
{
 if (dwExceptionCode == EXCEPTION_STACK_OVERFLOW)
 {
 _resetstkoflw ();
 return EXCEPTION_EXECUTE_HANDLER;
 }
 else
 {
 return EXCEPTION_CONTINUE_SEARCH;
 }
}

次の例では、エラーが正常に回避されます。

__try
{
    char *x = _alloca (i);
}
__except ((GetExceptionCode () == EXCEPTION_STACK_OVERFLOW) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
    // In this block the stack has already been unwound,
    // so this call will succeed.
_resetstkoflw ();
}