如何从 strftime 捕获格式错误作为异常?
How can I catch a format error from strftime as an exception?
我在 VS2013 C++ 程序中使用 ::strftime()
。有没有办法正确处理 "invalid format"
错误,而不会有停止整个程序的风险?
当我 运行 使用错误的格式编写如下函数代码时,比如 "%Y- %- m-%d"
,它是“GAME OVER”。我得到:
"Debug Assertion Failed ... Invalid format directive"
而且我只能停止应用程序(单元测试套件)。
有没有办法将其变成异常、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, '[=10=]' );
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()
文档说:
This function validates its parameters. If strDest, format, or timeptr is a null pointer, or if the tm data structure addressed by timeptr is invalid (for example, if it contains out of range values for the time or date), or if the format string contains an invalid formatting code, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, the function returns 0 and sets errno to EINVAL.
Parameter Validation 文档说:
Invalid Parameter Handler Routine
When a C Runtime Library function detects an invalid parameter, it captures some information about the error, and then calls a macro that wraps an invalid parameter handler dispatch function, one of _invalid_parameter, _invalid_parameter_noinfo, or _invalid_parameter_noinfo_noreturn. The dispatch function called depends on whether your code is, respectively, a debug build, a retail build, or the error is not considered recoverable.
In Debug builds, the invalid parameter macro usually raises a failed assertion and a debugger breakpoint before the dispatch function is called. When the code is executed, the assertion may be reported to the user in a dialog box that has "Abort", "Retry", and "Continue" or similar choices, depending on the operating system and runtime library version. These options allow the user to immediately terminate the program, to attach a debugger, or to let the existing code continue to run, which calls the dispatch function.
The invalid parameter handler dispatch function in turn calls the currently assigned invalid parameter handler. By default, the invalid parameter calls _invoke_watson which causes the application to "crash," that is, terminate and generate a mini-dump. If enabled by the operating system, a dialog box asks the user if they want to load the crash dump to Microsoft for analysis.
This behavior can be changed by using the functions _set_invalid_parameter_handler or _set_thread_local_invalid_parameter_handler to set the invalid parameter handler to your own function. If the function you specify does not terminate the application, control is returned to the function that received the invalid parameters. In the CRT, these functions will normally cease function execution, set errno to an error code, and return an error code. In many cases, the errno value and the return value are both EINVAL, indicating an invalid parameter. In some cases, a more specific error code is returned, such as EBADF for a bad file pointer passed in as a parameter. For more information on errno, see errno, _doserrno, _sys_errlist, and _sys_nerr.
我在 VS2013 C++ 程序中使用 ::strftime()
。有没有办法正确处理 "invalid format"
错误,而不会有停止整个程序的风险?
当我 运行 使用错误的格式编写如下函数代码时,比如 "%Y- %- m-%d"
,它是“GAME OVER”。我得到:
"Debug Assertion Failed ... Invalid format directive"
而且我只能停止应用程序(单元测试套件)。
有没有办法将其变成异常、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, '[=10=]' );
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()
文档说:
This function validates its parameters. If strDest, format, or timeptr is a null pointer, or if the tm data structure addressed by timeptr is invalid (for example, if it contains out of range values for the time or date), or if the format string contains an invalid formatting code, the invalid parameter handler is invoked, as described in Parameter Validation. If execution is allowed to continue, the function returns 0 and sets errno to EINVAL.
Parameter Validation 文档说:
Invalid Parameter Handler Routine
When a C Runtime Library function detects an invalid parameter, it captures some information about the error, and then calls a macro that wraps an invalid parameter handler dispatch function, one of _invalid_parameter, _invalid_parameter_noinfo, or _invalid_parameter_noinfo_noreturn. The dispatch function called depends on whether your code is, respectively, a debug build, a retail build, or the error is not considered recoverable.
In Debug builds, the invalid parameter macro usually raises a failed assertion and a debugger breakpoint before the dispatch function is called. When the code is executed, the assertion may be reported to the user in a dialog box that has "Abort", "Retry", and "Continue" or similar choices, depending on the operating system and runtime library version. These options allow the user to immediately terminate the program, to attach a debugger, or to let the existing code continue to run, which calls the dispatch function.
The invalid parameter handler dispatch function in turn calls the currently assigned invalid parameter handler. By default, the invalid parameter calls _invoke_watson which causes the application to "crash," that is, terminate and generate a mini-dump. If enabled by the operating system, a dialog box asks the user if they want to load the crash dump to Microsoft for analysis.
This behavior can be changed by using the functions _set_invalid_parameter_handler or _set_thread_local_invalid_parameter_handler to set the invalid parameter handler to your own function. If the function you specify does not terminate the application, control is returned to the function that received the invalid parameters. In the CRT, these functions will normally cease function execution, set errno to an error code, and return an error code. In many cases, the errno value and the return value are both EINVAL, indicating an invalid parameter. In some cases, a more specific error code is returned, such as EBADF for a bad file pointer passed in as a parameter. For more information on errno, see errno, _doserrno, _sys_errlist, and _sys_nerr.