Principle and usage of C++ Assert of assertion mechanism

  • 2020-05-12 02:55:39
  • OfStack

The MSDN text reads:

Evaluates an expression and, when the result is false, prints a diagnostic message and aborts the program.

Judge an expression, and if the result is false, output a diagnostic message and abort the program.


void assert(  
  int expression  
); 

Parameter: Expression (including pointers) that evaluates to nonzero or 0.

How it works: assert evaluates the expression expression, and if it is false (that is, 0), it prints an error message to stderr and then terminates the program by calling abort.

MSDN sample program


// crt_assert.c 
// compile with: /c 
#include <stdio.h> 
#include <assert.h> 
#include <string.h> 
 
void analyze_string( char *string );  // Prototype 
 
int main( void ) 
{ 
  char test1[] = "abc", *test2 = NULL, test3[] = ""; 
 
  printf ( "Analyzing string '%s'\n", test1 ); fflush( stdout ); 
  analyze_string( test1 ); 
  printf ( "Analyzing string '%s'\n", test2 ); fflush( stdout ); 
  analyze_string( test2 ); 
  printf ( "Analyzing string '%s'\n", test3 ); fflush( stdout ); 
  analyze_string( test3 ); 
} 
 
// Tests a string to see if it is NULL,  
// empty, or longer than 0 characters. 
void analyze_string( char * string ) 
{ 
  assert( string != NULL );    // Cannot be NULL 
  assert( *string != '\0' );    // Cannot be empty 
  assert( strlen( string ) > 2 ); // Length must exceed 2 
} 

The output


Analyzing string 'abc' 
Analyzing string '(null)' 
Assertion failed: string != NULL, file assert.cpp, line 25 
 
abnormal program termination 

Usage summary:

1) verify the legitimacy of the incoming parameter at the beginning of the function

Such as:


int resetBufferSize(int nNewSize)
{
 // function : Change the buffer size ,
 // parameter :nNewSize  New buffer length 
// The return value : Current buffer length 
// instructions : Keep the original message content the same    nNewSize<=0 Means clear buffer 
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);

 ...
}

2) each assert only tests one condition, because when multiple conditions are tested at the same time, if the assertion fails, it is impossible to intuitively judge which condition fails

Bad: assert (nOffset > =0 && nOffset+nSize < =m_nInfomationSize);

Good: assert (nOffset > = 0);
assert(nOffset+nSize < = m_nInfomationSize);


3) statements that change the environment cannot be used, because assert is only valid on DEBUG, if so, the application will encounter problems when it is actually running


Error: assert (i + + < 100)

This is because if there is an error, such as i=100 before execution, then this statement will not be executed, and i++ will not be executed.

Right: assert (i < 100);
i++;

4) assert and subsequent statements should leave 1 line blank to create a logical and visual sense of 1

5) in some places, assert cannot replace conditional filtering

ASSERT is only valid in the Debug version and is ignored if compiled to the Release version. (in C, ASSERT is a macro, not a function.) using ASSERT "assertions" is easy to output program errors at debug.

While assert() has similar functionality, it is a function specified in the ANSI C standard, and one important difference from ASSERT is that it can be used in the Release version.

The disadvantage of using assert is that frequent calls can greatly affect the performance of the program, adding extra overhead.

After debugging, you can do this by including #include < assert.h > To disable the assert call, insert #define NDEBUG before the statement. The sample code is as follows:

#include < stdio.h >
#define NDEBUG
#include < assert.h >

After adding #define NDEBUG, the output of the first example above is:


Analyzing string 'abc' 
Analyzing string '(null)' 
Analyzing string '' 

One of the most common interview questions:

The known function of memcpy is: void* memcpy(void *dest, const void* src, size_t count), where dest is the destination pointer and src is the source pointer. Instead of calling c++/c's memcpy library functions, write memcpy.


void* memcpy(void *dst, const void *src, size_t count)   
{   
  // The security check  
  assert( (dst != NULL) && (src != NULL) );   
 
  unsigned char *pdst = (unsigned char *)dst;   
  const unsigned char *psrc = (const unsigned char *)src;   
 
  // Prevent memory duplication  
  assert(!(psrc<=pdst && pdst<psrc+count));   
  assert(!(pdst<=psrc && psrc<pdst+count));   
 
  while(count--)   
  {   
    *pdst = *psrc;   
    pdst++;   
    psrc++;   
  }   
  return dst;   
}  

Related articles: