在生产代码的主程序逻辑中使用assert



假设我在自定义堆栈实现中有以下内容:

void Pop (Stack & s) {
assert (!isEmpty(s));
// implementation details of popping omitted
}

假设我想捕获坏的客户端使用,如弹出空堆栈。"Assert"在编译生产版本并通过NDEBUG标志禁用它之前,它是很棒的。如果您检测到不可恢复的错误,假设您最终要关闭断言,那么最专业的优雅死亡方式是什么?

是的,我知道有很多选项:使用"exit";将函数更改为返回类似c的错误代码;使用c++异常处理;只需忽略违规操作(将错误调用变为no-op);实现一个名为其他不会被关闭的东西的个人版本断言,等等。

什么是"最重要的"?这里要做什么?我只想快点死,留下一句有用的话。

为了好玩,我从标准库中创建了一个矢量实例,并将其弹出为空。这会导致seg错误,这对于标准库来说可能是可以接受的,但是我想在死之前捕获并报告这样的问题。
  1. 通常在生产代码中使用自定义assert宏。例如,
#define MYCOMPANY_ASSERT_FATAL(expression, msg, ret_val) if (!expression){ logger.fatal(msg); return ret_val;}
#define MYCOMPANY_ASSERT_WARN(...) .....
#define MYCOMPANY_ASSERT_ERROR(...) .....
  1. 基本上,应该被视为退出或消息传递的错误的严重级别取决于您的应用程序上下文层。简而言之,在大多数情况下,some_lib_func()无法决定退出自己的进程。这就是为什么some_lib_func()应该将错误信息传播给调用者。例如,
// library or middle module func couldn't decide to handle own application process, so after only logging return to caller 
bool read_csv(double& val) {
double val = 0;
bool ret = parse_csv_from_file(val);
MYCOMPANY_ASSERT_ERROR(ret, "failed to parse_csv_from_file", false); 
// return to caller with logging and error info(true/false here)
....
....
}
// application layer and need to handle for error which should be continue or message for user..
bool show_weather_in_foreign_country() {
bool ret = read_csv();
if (!ret) {
show_error_message();
}
// in this case read_csv error is trivial and you want to continue to process with proper message
...
}

在这种情况下,显示天气被认为是应用程序中的一个微不足道的过程,如果出现错误,您不希望退出整个应用程序,因此在显示适当的消息后继续处理。另一方面,下面的另一个例子很关键,尽管使用了read_csv的相同函数。

// application layer and need to handle for error which should be continue or message for user..
bool send_your_account_balance_in_securiities_to_your_wife() {
double val = 0;
bool ret = read_csv(val);
MYCOMPANY_ASSERT_FATAL(ret, "critical in my account balance", false);
// in this application context, the failure of read_csv is critical and never continue to process
// and return to caller. Caller should probably exit an own application
send_email_your_wife(val); 
// if send 0$ with some kind of mistake to you wife, she might die or kill you ...
...
}

因此,准备一些已定义的宏来传播错误和记录日志是非常有用的,可以使你的代码简单和安全,然后你需要根据你的应用程序上下文正确地使用它们。

最新更新