5

ユーザーが構成ファイルを介して日付の書式設定をカスタマイズできるようにする C++/MFC アプリケーションがあります。車輪を再発明したくないので、フォーマット文字列を CTime::Format("< format string >") に渡して、実際のフォーマットを行います。内部では、Format は標準 C 関数 strftime() のバリアントを呼び出します。

当然、ユーザーは誤って無効な書式文字列を入力する可能性があります。(たとえば、"%S" ではなく "%s" です。) これが発生すると、C ランタイムは無効な引数ハンドラーを呼び出し、既定ではアプリを終了します。(キャッチする例外はありません。アプリを終了するだけです。)

私の質問は、この信頼できない入力を適切に処理する方法です。理論的には、フォーマット文字列用の独自のパーサー/バリデーターを作成できますが、これは時間の無駄のように思えます。代わりに、私が思いついた最善の方法は、終了する代わりに無効な引数例外をスローする独自の (グローバル) 無効な引数ハンドラーを設定することでした。

void MyInvalidParameterHandler(
    const wchar_t* expression,
    const wchar_t* function, 
    const wchar_t* file, 
    unsigned int line, 
    uintptr_t pReserved)
{
    ::AfxThrowInvalidArgException();
}

これは機能しているようで、無効な引数の例外が発生することが「予想される」場合に、無効な引数の例外を明示的にキャッチ (および適切に処理) することができます。ただし、比較的「ローカルな」問題を解決するために、大規模なアプリケーションでグローバルなランタイム設定をオーバーライドしているのではないかと心配しています。

このアプローチは賢明ですか?または、この問題を解決するよりクリーンなアプローチはありますか?

4

1 に答える 1

3

このエラーを特定の時間にのみキャッチすることに関心がある場合は、無効なパラメーターハンドラーを一時的に置き換えて、Formatを呼び出したら元に戻すことができます。

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler);

// Your try/Format/catch code here

_set_invalid_parameter_handler(oldHandler);

もちろん、プログラムに複数のスレッドがある場合、設定中に別のスレッドが無効なパラメーターハンドラーを呼び出す可能性があると思います。その可能性を判断する必要があります。

独自の検証関数を作成する以外に、他にどのようにこれを実行できるかわかりません。

于 2010-02-24T14:16:49.977 に答える