c++ - 如何从 strftime 捕获格式错误作为异常?
问题描述
我::strftime()
在 VS2013 C++ 程序中使用。有没有办法"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, '\0' );
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 数据结构无效(例如,如果它包含超出范围的时间或日期值),或者如果格式字符串包含无效格式代码中,将调用无效的参数处理程序,如Parameter Validation中所述。如果允许继续执行,则函数返回 0 并将 errno 设置为 EINVAL。
参数验证文档说:
无效的参数处理程序例程
当 C 运行时库函数检测到无效参数时,它会捕获有关错误的一些信息,然后调用包装无效参数处理程序调度函数的宏,该函数是 _invalid_parameter、_invalid_parameter_noinfo 或 _invalid_parameter_noinfo_noreturn 之一。调用的调度函数取决于您的代码是分别是调试版本、零售版本还是错误被认为是不可恢复的。
在调试版本中,无效参数宏通常会在调用调度函数之前引发失败的断言和调试器断点。当代码被执行时,根据操作系统和运行时库版本,断言可能会在一个对话框中报告给用户,该对话框具有“Abort”、“Retry”和“Continue”或类似的选项。这些选项允许用户立即终止程序、附加调试器或让现有代码继续运行,这会调用调度函数。
无效参数处理程序调度函数依次调用当前分配的无效参数处理程序。默认情况下,无效参数调用 _invoke_watson 导致应用程序“崩溃”,即终止并生成一个小型转储。如果操作系统启用,则会出现一个对话框,询问用户是否要将故障转储加载到 Microsoft 进行分析。
可以通过使用函数_set_invalid_parameter_handler或_set_thread_local_invalid_parameter_handler将无效参数处理程序设置为您自己的函数来更改此行为。如果您指定的函数没有终止应用程序,则控制权返回给接收到无效参数的函数。在 CRT 中,这些函数通常会停止函数执行,将 errno 设置为错误代码,并返回错误代码。很多情况下errno值和返回值都是EINVAL,表示参数无效。在某些情况下,会返回更具体的错误代码,例如作为参数传入的错误文件指针的 EBADF。有关 errno 的详细信息,请参阅 errno、_doserrno、_sys_errlist 和 _sys_nerr。
推荐阅读
- python - 是否可以一次使用 pip 安装模块和包装脚本?
- laravel - 将新的自动增量列添加到现有表
- function - 用 Python 优雅地编写斐波那契数列
- javascript - for循环nodeJS中的Mongo查询
- javascript - 使用 moment.js 将秒转换为小时和分钟
- tsql - ABAP 域和数据类型理解
- pandas - 使用字典转换数据的 pandas 映射函数
- reactjs - 使用 react-icons 时导入错误
- javascript - 如何从 JSON 获取响应中捕获错误消息?
- javascript - 多种图像尺寸 | Firebase 存储