2010-02-24 30 views
5

我們有一個C++/MFC應用程序,它允許用戶通過配置文件自定義日期格式。不想重新發明輪子,我將格式字符串傳遞給CTime :: Format(「< format string>」)以執行實際的格式化。在封面下,Format調用標準C函數strftime()的變體。用不可信的格式字符串安全地調用strftime

當然,用戶可能會無意中輸入無效的格式字符串。 (例如,「%s」而不是「%S」)。發生這種情況時,C運行時會調用默認情況下退出應用程序的Invalid Argument Handler。 (沒有例外 - 趕上 - 只是應用程序退出。)

我的問題是如何優雅地處理這個不受信任的輸入。理論上,我可以爲格式字符串編寫我自己的解析器/驗證器,但這聽起來像浪費時間。相反,我會拿出最好的就是把我自己的(全球)無效的參數處理程序,其中代替退出,拋出一個無效的參數異常:

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

這似乎工作,並允許我明確在我「期待」它們發生的情況下捕捉(並優雅地處理)無效參數異常。然而,我擔心爲了解決一個相對「本地」的問題,我在一個大型應用程序中重寫全局運行時環境 - 我恨這個修復會導致其他問題。

這種方法是否合理?還是有更清晰的方法來解決這個問題?

回答

3

如果您只想在特定時間捕獲此錯誤,則可以暫時替換無效參數處理程序,然後在調用Format後將其設回。

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler); 

// Your try/Format/catch code here 

_set_invalid_parameter_handler(oldHandler); 

當然,我想這是可能的,如果你在你的程序有多個線程,同時它的設置另一個線程可能最終會調用您的無效參數處理程序。你將不得不確定這有多可能。

除了編寫自己的驗證功能,我不知道你還能怎麼做。

+0

謝謝你的建議。不幸的是,我的應用程序確實是多線程的,所以我不認爲我可以安全地來回切換處理程序。 (無效的參數處理程序是全局的,而不是線程特定的。) – 2010-02-24 14:19:43

+0

在這種情況下,我相信您需要創建自己的驗證功能。它不應該那麼難。如果您在CRT源代碼中查看strftime.c,您將看到一個名爲_expandtime的函數。它包含所有支持的格式說明符的case語句。你可以用它作爲你的函數的基礎。 – Dustin 2010-02-24 14:30:11

+0

一種可能性是添加您自己的無效參數處理程序。該文檔聲明,如果控制權返回到調用函數,它將返回一個錯誤代碼。 – Dustin 2010-02-24 15:24:34

相關問題