Безопасный вызов strftime с ненадежной форматной строкой - PullRequest
5 голосов
/ 24 февраля 2010

У нас есть приложение C ++ / MFC, которое позволяет пользователям настраивать форматирование даты через файлы конфигурации. Не желая изобретать велосипед, я передаю строку формата в CTime :: Format ("<строка формата>"), чтобы выполнить фактическое форматирование. Под прикрытием 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();
}

Это, похоже, работает и позволяет my явно перехватывать (и корректно обрабатывать) недопустимые исключения аргументов в тех случаях, когда я «ожидаю» их возникновения. Однако я обеспокоен тем, что я переопределяю глобальные параметры времени выполнения в большом приложении, чтобы решить относительно «локальную» проблему - я бы не хотел, чтобы это исправление вызывало дополнительные проблемы в других местах.

Разумен ли этот подход? Или есть более чистый подход к решению этой проблемы?

1 Ответ

3 голосов
/ 24 февраля 2010

Если вы заинтересованы только в перехвате этой ошибки в определенные моменты времени, вы можете временно заменить недопустимый обработчик параметров и затем сбросить его после вызова функции Format.

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler);

// Your try/Format/catch code here

_set_invalid_parameter_handler(oldHandler);

Конечно, я полагаю, что если в вашей программе несколько потоков, другой поток может в итоге вызвать ваш недопустимый обработчик параметров, пока он установлен. Вы должны будете определить, насколько это вероятно.

Кроме написания вашей собственной функции проверки, я не уверен, как еще вы могли бы сделать это.

...