GitHub
CERT Secure Coding

ERR06-C. Understand the termination behavior of assert() and abort()

The C Standard, subclause 7.2.1.1 [ ISO/IEC 9899:2011 ], defines assert() to have the following behavior:

The assert macro puts diagnostic tests into programs; it expands to a void expression. When it is executed, if expression (which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function—the latter are respectively the values of the pre-processing macros __ FILE_ _ and __ LINE_ _ and of the identifier __ func_ _) on the standard error stream in an implementation-defined format. It then calls the abort function.

Because assert() calls abort() , cleanup functions registered with atexit() are not called. If the intention of the programmer is to properly clean up in the case of a failed assertion, then runtime assertions should be replaced with static assertions where possible. (See DCL03-C. Use a static assertion to test the value of a constant expression .) When the assertion is based on runtime data, the assert should be replaced with a runtime check that implements the adopted error strategy (see ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy ).

See ERR04-C. Choose an appropriate termination strategy for more information on program termination strategies and MSC11-C. Incorporate diagnostic tests using assertions for more information on using the assert() macro.

Noncompliant Code Example

This noncompliant code example defines a function that is called before the program exits to clean up:

Non-compliant code
void cleanup(void) {
  /* Delete temporary files, restore consistent state, etc. */
}

int main(void) {
  if (atexit(cleanup) != 0) {
    /* Handle error */
  }

  /* ... */

  assert(/* Something bad didn't happen */);

  /* ... */
}

However, the code also has an assert , and if the assertion fails, the cleanup() function is not called.

Compliant Solution

In this compliant solution, the call to assert() is replaced with an if statement that calls exit() to ensure that the proper termination routines are run:

Compliant code
void cleanup(void) {
  /* Delete temporary files, restore consistent state, etc. */
}

int main(void) {
  if (atexit(cleanup) != 0) {
    /* Handle error */
  }

  /* ... */

  if (/* Something bad happened */) {
    exit(EXIT_FAILURE);
  }

  /* ... */
}

Risk Assessment

Unsafe use of abort() may leave files written in an inconsistent state. It may also leave sensitive temporary files on the file system.

Recommendation Severity Likelihood Detectable Repairable Priority Level
ERR06-C Medium Unlikely No No P2 L3

Automated Detection

Tool

Version

Checker

Description

Astrée
25.10
bad-function
bad-macro-use
Supported
Compass/ROSE



Can detect some violations of this rule. However, it can only detect violations involving abort() because assert() is implemented as a macro

LDRA tool suite
9.7.1
44 SEnhanced enforcement
Parasoft C/C++test

2025.2

CERT_C-ERR06-a

Do not use assertions

PC-lint Plus

1.4

586

Fully supported

PVS-Studio

7.42

V2021


RuleChecker
25.10
bad-function
bad-macro-use
Supported

Search for vulnerabilities resulting from the violation of this rule on the CERT website .

SEI CERT C++ Coding StandardVOID ERR06-CPP. Understand the termination behavior of assert() and abort()
ISO/IEC TR 24772:2013Termination Strategy [REU]

Bibliography

[ ISO/IEC 9899:2011 ]Subclause 7.2.1.1, "The assert Macro"