如何将strftime中的格式错误作为异常捕获

How can I catch a format error from strftime as an exception?

本文关键字:异常 错误 格式 strftime      更新时间:2023-10-16

我在VS2013 C++程序中使用::strftime()。有没有一种方法可以正确处理"invalid format"错误,而不会有停止整个程序的风险?

当我用错误的格式(比如"%Y- %- m-%d"(运行像下面函数这样的代码时;游戏结束";。我得到:

"调试断言失败。。。无效的格式指令";

和我只能停止应用程序(一个单元测试套件(。

有没有办法把它变成一个异常、一个errno代码等,这样我就可以正确地处理这种情况?

或者,还有其他我应该使用的功能吗?

或者,在调用strftime()之前,是否必须手动检查格式字符串

using namespace std;
string foo( string fmt ) // fmt: user supplied format - may be invalid
{
if (fmt.empty()) return "";
struct tm  myTm = ...; // get it some how
size_t n = 0;
size_t buflen = 2 * fmt.size();
while (buflen < 100) {
vector<char> buf( buflen, '' );
try {
n = ::strftime( buf.data(), buf.size(), fmt.c_str(), &myTm );
if (n>0)
return string( buf.data(), buf.data() + n );
if ((n == 0) && (34 == errno)) {
// 34 == "Result too large" (at least in VS2013)
buflen *= 2; // try with larger buffer
continue;
}
//   I NEVER REACH THIS POINT!  :-(
throw runtime_error( "please check your format string!" );
}
catch (...) {
//   I NEVER REACH THIS POINT!  :-(
throw runtime_error( "please check your format string" );
}
}
throw runtime_error( "max buffer size reached" );
}

strftime()文档中写道:

此函数验证其参数。如果strDest、format或timeptr是空指针,或者timeptr寻址的tm数据结构无效(例如,如果它包含超出时间或日期范围的值(,或者格式字符串包含无效的格式化代码,则会调用无效参数处理程序,如参数验证中所述。如果允许继续执行,函数将返回0并将errno设置为EINVAL。

参数验证文档中写道:

无效参数处理程序

当C运行库函数检测到无效参数时,它会捕获有关错误的一些信息,然后调用一个宏来包装无效参数处理程序调度函数,该函数是_invalid_parameter、_invalid_paarameter_noinfo或_invalid_paparameter_noiinfo_noreturn之一。调用的调度函数取决于您的代码分别是调试版本、零售版本,还是错误被认为是不可恢复的。

在调试生成中,无效参数宏通常会在调用调度函数之前引发失败断言和调试器断点。当代码被执行时,断言可以在对话框中报告给用户;中止"重试";,以及";继续";或类似的选择,这取决于操作系统和运行库版本。这些选项允许用户立即终止程序、附加调试器或让现有代码继续运行,从而调用调度函数。

无效参数处理程序调度函数依次调用当前分配的无效参数处理函数。默认情况下,无效参数调用_invoke_watson,导致应用程序";崩溃;即终止并生成一个小型转储。如果操作系统启用,则会出现一个对话框,询问用户是否要将崩溃转储加载到Microsoft进行分析。

可以通过使用函数_set_invalid_parameter_handler或_set_thread_local_invalid_paarameter_handler将无效参数处理程序设置为您自己的函数来更改此行为。如果指定的函数没有终止应用程序,则控制权将返回到接收到无效参数的函数。在CRT中,这些函数通常会停止函数执行,将errno设置为错误代码,并返回错误代码。在许多情况下,errno值和返回值都是EINVAL,表示参数无效。在某些情况下,会返回更具体的错误代码,例如作为参数传入的错误文件指针的EBADF。有关errno的详细信息,请参见errno、_doserrno、_sys_errlist和_sys_nerr。