Caffe源码分析——CHECK宏方法

写读Blob源码的时候,读完blob.hpp后,发现其中存在如下的这些方法。下面我们详细的来分析这些方法的源码以及它们的函数功能。

  • CHECK_EQ()
  • CHECK_LE()
  • CHECK_GE()
  • CHECK_LT()

CHECK方法是封装在GLOG库中,而GLOG库是Google开发的用于记录应用程序的使用库,提供基于C++标准输入输出流形式的接口,记录时可以选择不同的日志级别,方便将重要日志和普通日志分开。 GLOG 提供如下的CHECK方法:

代码位于 /usr/include/glog/logging.h

// Equality/Inequality checks - compare two values, and log a FATAL message
// including the two values when the result is not as expected.  The values
// must have operator<<(ostream, ...) defined.
//
// You may append to the error message like so:
//   CHECK_NE(1, 2) << ": The world must be ending!";
//
// We are very careful to ensure that each argument is evaluated exactly
// once, and that anything which is legal to pass as a function argument is
// legal here.  In particular, the arguments may be temporary expressions
// which will end up being destroyed at the end of the apparent statement,
// for example:
//   CHECK_EQ(string("abc")[1], 'b');
//
// WARNING: These don't compile correctly if one of the arguments is a pointer
// and the other is NULL. To work around this, simply static_cast NULL to the
// type of the desired pointer.

#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2) #相当于assert(val1 == val2)
# release下可用,如果检测为true,则返回NULL,否则返回一个有明确提示信息的字符串指针,并输出改信息,然后程序宕机

#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2) #相当于assert(val1 != val2)
#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2) #相当于assert(val1 <= val2)
#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2) #相当于assert(val1 < val2)
#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2) #相当于assert(val1 >= val2)
#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2) #相当于assert(val1 > val2)

 到此,我们已经搞清楚CEHCK函数具有什么功能,我们接着去看,现在我们来查看CHECK_OP 源码部分,宏定义的代码如下:

 代码位于 /usr/include/glog/logging.h

#if GOOGLE_STRIP_LOG <= 3
#define CHECK_OP(name, op, val1, val2) \
  CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
#else
#define CHECK_OP(name, op, val1, val2) \
  CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal)
#endif // STRIP_LOG <= 3

GOOGLE_STRIP_LOG是限制等级,低于这个等级的都不会被显示。 

 下面,我们查看CHECK_OP_LOG()部分源码

#if defined(STATIC_ANALYSIS)
// Only for static analysis tool to know that it is equivalent to assert
#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2))
#elif !defined(NDEBUG)
// In debug mode, avoid constructing CheckOpStrings if possible,
// to reduce the overhead of CHECK statments by 2x.
// Real DCHECK-heavy tests have seen 1.5x speedups.

// The meaning of "string" might be different between now and 
// when this macro gets invoked (e.g., if someone is experimenting
// with other string implementations that get defined after this
// file is included).  Save the current meaning now and use it 
// in the macro.
typedef std::string _Check_string;
#define CHECK_OP_LOG(name, op, val1, val2, log)                         \
  while (google::_Check_string* _result =                \
         google::Check##name##Impl(                      \
             google::GetReferenceableValue(val1),        \
             google::GetReferenceableValue(val2),        \
             #val1 " " #op " " #val2))                                  \
    log(__FILE__, __LINE__,                                             \
        google::CheckOpString(_result)).stream()
#else
// In optimized mode, use CheckOpString to hint to compiler that
// the while condition is unlikely.
#define CHECK_OP_LOG(name, op, val1, val2, log)                         \
  while (google::CheckOpString _result =                 \
         google::Check##name##Impl(                      \
             google::GetReferenceableValue(val1),        \
             google::GetReferenceableValue(val2),        \
             #val1 " " #op " " #val2))                                  \
    log(__FILE__, __LINE__, _result).stream()
#endif  // STATIC_ANALYSIS, !NDEBUG

这里我们举个例子,以 CHECK_EQ(1,2) 为例,来看其执行过程。

CHECK_EQ(1,2) --->   CHECK_OP(_NE, ==, 1, 2) --->
CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)   --->

#define CHECK_OP_LOG(_NE, ==, 1, 2, google::LogMessageFatal)                         \
  while (google::_Check_string* _result =                \
         google::Check_EQ_Impl(                      \
             google::GetReferenceableValue(1),        \
             google::GetReferenceableValue(2),        \
             "1== 2"))                                  \
    log(__FILE__, __LINE__,                                             \
        google::CheckOpString(_result)).stream()

其中 google::Check_EQ_Impl() 也是通过宏预先定义的,这个宏的定义如下:

// Helper functions for CHECK_OP macro.
// The (int, int) specialization works around the issue that the compiler
// will not instantiate the template version of the function on values of
// unnamed enum type - see comment below.
#define DEFINE_CHECK_OP_IMPL(name, op) \
  template <typename T1, typename T2> \
  inline std::string* name##Impl(const T1& v1, const T2& v2,    \
                            const char* exprtext) { \
    if (GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
    else return MakeCheckOpString(v1, v2, exprtext); \
  } \
  inline std::string* name##Impl(int v1, int v2, const char* exprtext) { \
    return name##Impl<int, int>(v1, v2, exprtext); \
  }

// We use the full name Check_EQ, Check_NE, etc. in case the file including
// base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
// This happens if, for example, those are used as token names in a
// yacc grammar.
DEFINE_CHECK_OP_IMPL(Check_EQ, ==)  // Compilation error with CHECK_EQ(NULL, x)?
DEFINE_CHECK_OP_IMPL(Check_NE, !=)  // Use CHECK(x == NULL) instead.
DEFINE_CHECK_OP_IMPL(Check_LE, <=)
DEFINE_CHECK_OP_IMPL(Check_LT, <)
DEFINE_CHECK_OP_IMPL(Check_GE, >=)
DEFINE_CHECK_OP_IMPL(Check_GT, > )
#undef DEFINE_CHECK_OP_IMPL

最后我们可以发现CHECK_EQ(1,2) 真正的执行过程是

CHECK_EQ(1, 2) ------->
while (google::_Check_string* _result =                \
         google::Check_EQ_Impl(                      \
             google::GetReferenceableValue(1),        \
             google::GetReferenceableValue(2),        \
             "1== 2"))                                  \
    log(__FILE__, __LINE__,                                             \
        google::CheckOpString(_result)).stream()

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值