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:
parent
67b859cf13
commit
13ae13bf43
@ -1,19 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* Permanent Assert -> always active
|
* @file
|
||||||
* Debug Assert -> active only if DEBUG_ASSERT_ON is present
|
* 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
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "utils/stacktrace.hpp"
|
#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
|
#ifdef STACKTRACE_ASSERT_ON
|
||||||
#define __handle_assert_message(message) \
|
#define __handle_assert_message(message) \
|
||||||
Stacktrace stacktrace; \
|
Stacktrace stacktrace; \
|
||||||
@ -26,38 +26,84 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* permanent assertion will always be active
|
* Always check that the condition is satisfied, otherwise abort the program.
|
||||||
* when condition is not satisfied program will exit
|
|
||||||
*
|
*
|
||||||
* a good use-case for this type of assert is during unit testing because
|
* Unlike @c debug_assert, @c permanent_assert is always active. A good use-case
|
||||||
* assert has to stay active all the time
|
* 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) \
|
#define permanent_assert(condition, message) \
|
||||||
if (!(condition)) { \
|
if (!(condition)) { \
|
||||||
std::ostringstream s; \
|
std::ostringstream s; \
|
||||||
s << message; \
|
s << message; \
|
||||||
__handle_assert_message(s.str()); \
|
__handle_assert_message(s.str()); \
|
||||||
std::exit(EXIT_FAILURE); \
|
std::abort(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define permanent_fail(message) \
|
/**
|
||||||
{ \
|
* Always abort the program with given message.
|
||||||
std::ostringstream s; \
|
*
|
||||||
s << message; \
|
* Unlike @c debug_fail, @c permanent_fail is always active. This should be used
|
||||||
__handle_assert_message(s.str()); \
|
* like @c permanent_assert, but when the condition cannot be a simple
|
||||||
std::exit(EXIT_FAILURE); \
|
* expression.
|
||||||
}
|
*
|
||||||
/** \
|
* @param message Message to display before aborting.
|
||||||
* debug assertion is more like standard C assert but with custom \
|
*
|
||||||
* define which controls when the assertion will be active \
|
* @sa permanent_assert
|
||||||
* \
|
* @sa debug_assert
|
||||||
* could be used wherever the standard C assert is used but \
|
* @sa debug_fail
|
||||||
* the user should not forget about DEBUG_ASSERT_ON define \
|
|
||||||
*/
|
*/
|
||||||
|
#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
|
#ifdef DEBUG_ASSERT_ON
|
||||||
#define debug_assert(condition, message) permanent_assert(condition, message)
|
#define debug_assert(condition, message) permanent_assert(condition, message)
|
||||||
#define debug_fail(message) permanent_fail(message)
|
#define debug_fail(message) permanent_fail(message)
|
||||||
#else
|
#else
|
||||||
#define debug_assert(condition, message) {}
|
#define debug_assert(condition, message) \
|
||||||
#define debug_fail(message) {}
|
{}
|
||||||
|
#define debug_fail(message) \
|
||||||
|
{}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user