android-CHECK_xxx分析
创始人
2024-02-27 04:36:20
0

android-CHECK_xxx

在这里插入图片描述
在android源码中有不少类似这样的用法,上图中就是检查获得的hal版本是否大于等于版本1_3,满足继续往下走,不满足则assert,并报错。
接下来就展开看看CHECK_xx家族:

用法

类型用法含义
CHECK_EQ(val1, val2)==检查左右val1与val2是否相等,相等则通过,否则assert并输出error log
CHECK_NE(val1, val2)!=检查左右val1与val2是否不相等,不相等则通过,否则assert并输出error log
CHECK_LE(val1, val2)检查左右val1是否小于等于val2,小于等于则通过,否则assert并输出error log
CHECK_LT(val1, val2)检查左右val1是否小于val2,小于则通过,否则assert并输出error log
CHECK_GE(val1, val2)检查左右val1是否大于等于val2,大于等于则通过,否则assert并输出error log
CHECK_GT(val1, val2)检查左右val1是否大于val2,大于则通过,否则assert并输出error log
#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(LT, < , val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)#define CHECK_OP(name, op, val1, val2) CHECK((val1) op (val2))
// Helper macro for binary operators.
// Don't use this macro directly in your code, use CHECK_EQ et al below.
// The 'switch' is used to prevent the 'else' from being ambiguous when the
// macro is used in an 'if' clause such as:
// if (a == 1)
//   CHECK_EQ(2, a);
#define CHECK_OP(name, op, val1, val2)                                         \switch (0) case 0: default:                                                  \if (::logging::CheckOpResult true_if_passed =                                \::logging::Check##name##Impl((val1), (val2),                             \#val1 " " #op " " #val2))                   \;                                                                           \else                                                                         \::logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream()#endif  // !(OFFICIAL_BUILD && NDEBUG)

switch (0) case 0: default:当宏被用在一个if子句中时,'switch’用于防止’else’不明确

以CHECK_GE为例分析源码

#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)

CHECK_OP(GE, >=, val1, val2)展开后

if (::logging::CheckOpResult true_if_passed = ::logging::CheckGEImpl((val1), (val2), "val1 >= val2");
else::logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream()

实际上跳到另一个宏Check##name##Impl去执行了,看返回结果true_if_passed是不是为真,若为假则打印出信息,这里的LogMessage是一个类,根据文件名、行号、日志级别构建对象,之后执行LogMessage::stream()输出信息
看看宏Check##name##Impl

  inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \if (ANALYZER_ASSUME_TRUE(v1 op v2))                                      \return NULL;                                                           \else                                                                     \return ::logging::MakeCheckOpString(v1, v2, names);                    \}

CheckGEImpl展开后,在这里#op是>=

    if (ANALYZER_ASSUME_TRUE(val1 >= val2))return NULL;elsereturn ::logging::MakeCheckOpString(v1, v2, names);

看看宏ANALYZER_ASSUME_TRUE,在clang_analyzer中加静态分析,返回参数val1 >= val2是否为真,若为真返回NULL,Check_xxx通过。ANALYZER_ASSUME_TRUE常与断言和类断言函数一起使用。

inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) {return false;
}inline constexpr bool AnalyzerAssumeTrue(bool arg) {// AnalyzerNoReturn() is invoked and analysis is terminated if |arg| is// false.return arg || AnalyzerNoReturn();
}#define ANALYZER_ASSUME_TRUE(arg) logging::AnalyzerAssumeTrue(!!(arg))

若ANALYZER_ASSUME_TRUE返回假,则进到else中的MakeCheckOpString,负责构建错误消息字符串,就不再展开了

// Build the error message string.  This is separate from the "Impl"
// function template because it is not performance critical and so can
// be out of line, while the "Impl" code should be inline.  Caller
// takes ownership of the returned string.
template
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {std::ostringstream ss;ss << names << " (";MakeCheckOpValueString(&ss, v1);ss << " vs. ";MakeCheckOpValueString(&ss, v2);ss << ")";std::string* msg = new std::string(ss.str());return msg;
}

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...