常见错误28:断言(assert宏) 的副作用
#define有很多种用法,定义在<cassert>中的assert有好处,鼓励多用--前提是用好
#define有很多种用法,定义在<cassert>中的assert有好处,鼓励多用--前提是用好
但问题就在于能不能用好它。
myassert.h
#ifndef MYASSERT_H
#define MYASSERT_H
#include <iostream>
// undefine standard assert so we can show our own version
// don't do this in production code!
#undef assert
#ifndef NDEBUG
#define assert(e) ((e) \
? ((void)0) \
:__assert_failed(#e,__FILE__,__LINE__) )
void __assert_failed(const char *m, const char *file, int line ) {
std::cerr << "Assertion failed: " << m << " file: " << file
<< " line: " << line << std::endl;
// pedagogic code: comment out abort to allow multiple assertions
// std::abort();
}
#else
#define assert(e) ((void)0)
#endif
//如果NDEUBG有定义,那么我们就没有在调试模式,assert宏就会展开成一个空操作。否则,
//我们就处在调试模式下,(在此特定实现中)assert宏就会展开成一个空操作。
//与注释不同的是,由于违反了assert宏的正确性校验的错误来说都被更正了,因为“调用abort”
//这种后果会使得“代码需要维护”这件事必须马上完成:
#endif
myassert.cpp
#include "myassert.h"
#include <vector>
#include <deque>
template <typename T>
bool process( const T & )
{ return false; }
template <class Cont>
void doit( Cont &c, int index ) {
assert( index >= 0 && index < c.size() ); // #1
assert( process( c[index] ) ); // #2
//...
}
//assert宏并非万金油,但它的确在位于注释和异常之间的某个位置扮演了代码文档化及
//捕获非法行为的适当角色
int main() {
int x = 23;
assert( x-12<2 );
std::vector<int> aVector(10);
doit( aVector, 9 );
std::deque<double> aList;
//doit( aList, 1 ); // uncomment to have runtime error
// not caught by assertion
return 0;
}
输出
Assertion failed: x-12<2 file: 位置省略 myassert.cpp line: 19
Assertion failed: process( c[index] ) file: 位置省略 myassert.cpp line: 12