Make asserts abort the program instead of exiting cleanly

Summary:
Since assertions should signify an abnormal program condition, it makes
sense for them to call `std::abort`. This way, we'll get a core dump
which can be inspected in a debugger.

Update utils/assert.hpp documentation

Reviewers: florijan, buda, mislav.bradac

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D475
This commit is contained in:
Teon Banek 2017-06-14 17:22:26 +02:00
parent 67b859cf13
commit 13ae13bf43

View File

@ -1,19 +1,19 @@
/**
* Permanent Assert -> always active
* Debug Assert -> active only if DEBUG_ASSERT_ON is present
* @file
* This file defines @c permanent_assert and @c debug_assert.
*
* If @c STACKTRACE_ASSERT_ON is defined, when an assertion fails, the full
* stack trace will be printed to @c stderr, otherwise just the basic
* information will be printed out (message, file, line)
*/
#pragma once
#include <cstdlib>
#include <iostream>
#include <sstream>
#include "utils/stacktrace.hpp"
/**
* if STACKTRACE_ASSERT_ON is defined the full stacktrace will be printed on
* stderr otherwise just the basic information will be printed out (message,
* file, line)
*/
#ifdef STACKTRACE_ASSERT_ON
#define __handle_assert_message(message) \
Stacktrace stacktrace; \
@ -26,38 +26,84 @@
#endif
/**
* permanent assertion will always be active
* when condition is not satisfied program will exit
* Always check that the condition is satisfied, otherwise abort the program.
*
* a good use-case for this type of assert is during unit testing because
* assert has to stay active all the time
* Unlike @c debug_assert, @c permanent_assert is always active. A good use-case
* for this type of assert is during unit testing, because assert has to be
* active regardless of the build type.
*
* @param condition Expression which has to evaluate to @c true.
* @param message Message that is to be displayed before aborting, if the
* evaluated @c condition is @c false.
*
* @sa permanent_fail
* @sa debug_assert
* @sa debug_fail
*/
#define permanent_assert(condition, message) \
if (!(condition)) { \
std::ostringstream s; \
s << message; \
__handle_assert_message(s.str()); \
std::exit(EXIT_FAILURE); \
std::abort(); \
}
#define permanent_fail(message) \
{ \
std::ostringstream s; \
s << message; \
__handle_assert_message(s.str()); \
std::exit(EXIT_FAILURE); \
}
/** \
* debug assertion is more like standard C assert but with custom \
* define which controls when the assertion will be active \
* \
* could be used wherever the standard C assert is used but \
* the user should not forget about DEBUG_ASSERT_ON define \
/**
* Always abort the program with given message.
*
* Unlike @c debug_fail, @c permanent_fail is always active. This should be used
* like @c permanent_assert, but when the condition cannot be a simple
* expression.
*
* @param message Message to display before aborting.
*
* @sa permanent_assert
* @sa debug_assert
* @sa debug_fail
*/
#define permanent_fail(message) \
{ \
std::ostringstream s; \
s << message; \
__handle_assert_message(s.str()); \
std::abort(); \
}
/**
* @def debug_assert(condition, message)
* Check that the condition is satisfied, otherwise abort the program.
*
* This is like @c permanent_assert, but the @c DEBUG_ASSERT_ON define controls
* whether this assertion is active. Without the define, @c debug_assert will do
* nothing. Therefore, this is more like the standard C @c assert facility and
* it should be used as such. For example, validating pre and post conditions of
* a function.
*
* @sa debug_fail
* @sa permanent_assert
* @sa permanent_fail
*/
/**
* @def debug_fail(message)
* Abort the program with given message.
*
* This is like @c permanent_fail, but the @c DEBUG_ASSERT_ON define controls
* whether this assertion is active. Without the define, @c debug_fail will do
* nothing. This should be used like @c debug_assert, but when the condition
* cannot be a simple expression.
*
* @sa debug_assert
* @sa permanent_assert
* @sa permanent_fail
*/
#ifdef DEBUG_ASSERT_ON
#define debug_assert(condition, message) permanent_assert(condition, message)
#define debug_fail(message) permanent_fail(message)
#else
#define debug_assert(condition, message) {}
#define debug_fail(message) {}
#define debug_assert(condition, message) \
{}
#define debug_fail(message) \
{}
#endif