SDL3pp
A slim C++ wrapper for SDL3
Loading...
Searching...
No Matches
Macros | Typedefs | Functions | Variables
Assertions

A helpful assertion macro! More...

Macros

#define SDL_ASSERT_LEVEL   SomeNumberBasedOnVariousFactors
 The level of assertion aggressiveness.
 
#define SDL_TriggerBreakpoint()   TriggerABreakpointInAPlatformSpecificManner
 Attempt to tell an attached debugger to pause.
 
#define SDL_FUNCTION   __FUNCTION__
 A macro that reports the current function being compiled.
 
#define SDL_FILE   __FILE__
 A macro that reports the current file being compiled.
 
#define SDL_LINE   __LINE__
 A macro that reports the current line number of the file being compiled.
 
#define SDL_NULL_WHILE_LOOP_CONDITION   (0)
 A macro for wrapping code in do {} while (0); without compiler warnings.
 
#define SDL_disabled_assert(condition)
 The macro used when an assertion is disabled.
 
#define SDL_AssertBreakpoint()   SDL_TriggerBreakpoint()
 The macro used when an assertion triggers a breakpoint.
 
#define SDL_enabled_assert(condition)
 The macro used when an assertion is enabled.
 
#define SDL_assert(condition)    if (assertion_enabled && (condition)) { trigger_assertion; }
 An assertion test that is normally performed only in debug builds.
 
#define SDL_assert_release(condition)   SDL_disabled_assert(condition)
 An assertion test that is performed even in release builds.
 
#define SDL_assert_paranoid(condition)   SDL_disabled_assert(condition)
 An assertion test that is performed only when built with paranoid settings.
 
#define SDL_assert_always(condition)   SDL_enabled_assert(condition)
 An assertion test that is always performed.
 

Typedefs

using SDL::AssertState = SDL_AssertState
 Possible outcomes from a triggered assertion.
 
using SDL::AssertData = SDL_AssertData
 Information about an assertion failure.
 
using SDL::AssertionHandler = SDL_AssertionHandler
 A Callback that fires when an SDL assertion fails.
 
using SDL::AssertionHandlerCB = std::function< SDL_AssertState(const SDL_AssertData *)>
 A callback that fires when an SDL assertion fails.
 

Functions

AssertState SDL::ReportAssertion (AssertData *data, StringParam func, StringParam file, int line)
 Never call this directly.
 
void SDL::SetAssertionHandler (AssertionHandler handler, void *userdata)
 Set an application-defined assertion handler.
 
void SDL::SetAssertionHandler (AssertionHandlerCB handler)
 Set an application-defined assertion handler.
 
AssertionHandler SDL::GetDefaultAssertionHandler ()
 Get the default assertion handler.
 
AssertionHandler SDL::GetAssertionHandler (void **puserdata)
 Get the current assertion handler.
 
AssertionHandlerCB SDL::GetAssertionHandler ()
 Get the current assertion handler.
 
const AssertDataSDL::GetAssertionReport ()
 Get a list of all assertion failures.
 
void SDL::ResetAssertionReport ()
 Clear the list of all assertion failures.
 

Variables

constexpr AssertState SDL::ASSERTION_RETRY = SDL_ASSERTION_RETRY
 Retry the assert immediately.
 
constexpr AssertState SDL::ASSERTION_BREAK = SDL_ASSERTION_BREAK
 Make the debugger trigger a breakpoint.
 
constexpr AssertState SDL::ASSERTION_ABORT = SDL_ASSERTION_ABORT
 Terminate the program.
 
constexpr AssertState SDL::ASSERTION_IGNORE = SDL_ASSERTION_IGNORE
 Ignore the assert.
 
constexpr AssertState SDL::ASSERTION_ALWAYS_IGNORE = SDL_ASSERTION_ALWAYS_IGNORE
 Ignore the assert from now on.
 

Detailed Description

SDL assertions operate like your usual assert macro, but with some added features:

To use it: compile a debug build and just sprinkle around tests to check your code!

Macro Definition Documentation

◆ SDL_assert

#define SDL_assert (   condition)     if (assertion_enabled && (condition)) { trigger_assertion; }

This macro is enabled when the SDL_ASSERT_LEVEL is >= 2, otherwise it is disabled. This is meant to only do these tests in debug builds, so they can tend to be more expensive, and they are meant to bring everything to a halt when they fail, with the programmer there to assess the problem.

In short: you can sprinkle these around liberally and assume they will evaporate out of the build when building for end-users.

When assertions are disabled, this wraps condition in a sizeof operator, which means any function calls and side effects will not run, but the compiler will not complain about any otherwise-unused variables that are only referenced in the assertion.

One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.

Parameters
conditionboolean value to test.
Thread safety:
It is safe to call this macro from any thread.
Since
This macro is available since SDL 3.2.0.

◆ SDL_assert_always

#define SDL_assert_always (   condition)    SDL_enabled_assert(condition)

This macro is always enabled no matter what SDL_ASSERT_LEVEL is set to. You almost never want to use this, as it could trigger on an end-user's system, crashing your program.

One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.

Parameters
conditionboolean value to test.
Thread safety:
It is safe to call this macro from any thread.
Since
This macro is available since SDL 3.2.0.

◆ SDL_ASSERT_LEVEL

#define SDL_ASSERT_LEVEL   SomeNumberBasedOnVariousFactors

This value changes depending on compiler options and other preprocessor defines.

It is currently one of the following values, but future SDL releases might add more:

  • 0: All SDL assertion macros are disabled.
  • 1: Release settings: SDL_assert disabled, SDL_assert_release enabled.
  • 2: Debug settings: SDL_assert and SDL_assert_release enabled.
  • 3: Paranoid settings: All SDL assertion macros enabled, including SDL_assert_paranoid.
Since
This macro is available since SDL 3.2.0.

◆ SDL_assert_paranoid

#define SDL_assert_paranoid (   condition)    SDL_disabled_assert(condition)

This macro is enabled when the SDL_ASSERT_LEVEL is >= 3, otherwise it is disabled. This is a higher level than both release and debug, so these tests are meant to be expensive and only run when specifically looking for extremely unexpected failure cases in a special build.

When assertions are disabled, this wraps condition in a sizeof operator, which means any function calls and side effects will not run, but the compiler will not complain about any otherwise-unused variables that are only referenced in the assertion.

One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.

Parameters
conditionboolean value to test.
Thread safety:
It is safe to call this macro from any thread.
Since
This macro is available since SDL 3.2.0.

◆ SDL_assert_release

#define SDL_assert_release (   condition)    SDL_disabled_assert(condition)

This macro is enabled when the SDL_ASSERT_LEVEL is >= 1, otherwise it is disabled. This is meant to be for tests that are cheap to make and extremely unlikely to fail; generally it is frowned upon to have an assertion failure in a release build, so these assertions generally need to be of more than life-and-death importance if there's a chance they might trigger. You should almost always consider handling these cases more gracefully than an assert allows.

When assertions are disabled, this wraps condition in a sizeof operator, which means any function calls and side effects will not run, but the compiler will not complain about any otherwise-unused variables that are only referenced in the assertion.

One can set the environment variable "SDL_ASSERT" to one of several strings ("abort", "break", "retry", "ignore", "always_ignore") to force a default behavior, which may be desirable for automation purposes. If your platform requires GUI interfaces to happen on the main thread but you're debugging an assertion in a background thread, it might be desirable to set this to "break" so that your debugger takes control as soon as assert is triggered, instead of risking a bad UI interaction (deadlock, etc) in the application.

  • Parameters
    conditionboolean value to test.
    Thread safety:
    It is safe to call this macro from any thread.
    Since
    This macro is available since SDL 3.2.0.

◆ SDL_AssertBreakpoint

#define SDL_AssertBreakpoint ( )    SDL_TriggerBreakpoint()

This isn't for direct use by apps; use SDL_assert or SDL_TriggerBreakpoint instead.

Since
This macro is available since SDL 3.2.0.

◆ SDL_disabled_assert

#define SDL_disabled_assert (   condition)
Value:
do { \
(void)sizeof((condition)); \
#define SDL_NULL_WHILE_LOOP_CONDITION
A macro for wrapping code in do {} while (0); without compiler warnings.
Definition SDL3pp_assert.h:135

This isn't for direct use by apps, but this is the code that is inserted when an SDL_assert is disabled (perhaps in a release build).

The code does nothing, but wraps condition in a sizeof operator, which generates no code and has no side effects, but avoid compiler warnings about unused variables.

Parameters
conditionthe condition to assert (but not actually run here).
Since
This macro is available since SDL 3.2.0.

◆ SDL_enabled_assert

#define SDL_enabled_assert (   condition)
Value:
do { \
while (!(condition)) { \
static struct SDL_AssertData sdl_assert_data = { \
0, 0, #condition, 0, 0, 0, 0}; \
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion( \
&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
continue; /* go again. */ \
} else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
SDL_AssertBreakpoint(); \
} \
break; /* not retrying. */ \
} \
#define SDL_FILE
A macro that reports the current file being compiled.
Definition SDL3pp_assert.h:108
#define SDL_FUNCTION
A macro that reports the current function being compiled.
Definition SDL3pp_assert.h:101
#define SDL_LINE
A macro that reports the current line number of the file being compiled.
Definition SDL3pp_assert.h:115

This isn't for direct use by apps, but this is the code that is inserted when an SDL_assert is enabled.

The do {} while(0) avoids dangling else problems:

if (x) SDL_assert(y); else blah();
#define SDL_assert(condition)
An assertion test that is normally performed only in debug builds.
Definition SDL3pp_assert.h:311

... without the do/while, the "else" could attach to this macro's "if". We try to handle just the minimum we need here in a macro...the loop, the static vars, and break points. The heavy lifting is handled in SDL_ReportAssertion().

Parameters
conditionthe condition to assert.
Since
This macro is available since SDL 3.2.0.

◆ SDL_FILE

#define SDL_FILE   __FILE__
Since
This macro is available since SDL 3.2.0.

◆ SDL_FUNCTION

#define SDL_FUNCTION   __FUNCTION__

If SDL can't figure how the compiler reports this, it will use "???".

Since
This macro is available since SDL 3.2.0.

◆ SDL_LINE

#define SDL_LINE   __LINE__
Since
This macro is available since SDL 3.2.0.

◆ SDL_NULL_WHILE_LOOP_CONDITION

#define SDL_NULL_WHILE_LOOP_CONDITION   (0)

Visual Studio with really aggressive warnings enabled needs this to avoid compiler complaints.

the do {} while (0); trick is useful for wrapping code in a macro that may or may not be a single statement, to avoid various C language accidents.

To use:

do { SomethingOnce(); } while (SDL_NULL_WHILE_LOOP_CONDITION (0));
Since
This macro is available since SDL 3.2.0.

◆ SDL_TriggerBreakpoint

#define SDL_TriggerBreakpoint ( )    TriggerABreakpointInAPlatformSpecificManner

This allows an app to programmatically halt ("break") the debugger as if it had hit a breakpoint, allowing the developer to examine program state, etc.

This is a macro–not a function–so that the debugger breaks on the source code line that used SDL_TriggerBreakpoint and not in some random guts of SDL. SDL_assert uses this macro for the same reason.

If the program is not running under a debugger, SDL_TriggerBreakpoint will likely terminate the app, possibly without warning. If the current platform isn't supported, this macro is left undefined.

Thread safety:
It is safe to call this macro from any thread.
Since
This macro is available since SDL 3.2.0.

Typedef Documentation

◆ AssertData

using SDL::AssertData = typedef SDL_AssertData

This structure is filled in with information about a triggered assertion, used by the assertion handler, then added to the assertion report. This is returned as a linked list from SDL_GetAssertionReport().

Since
This struct is available since SDL 3.2.0.

◆ AssertionHandler

using SDL::AssertionHandler = typedef SDL_AssertionHandler
Parameters
dataa pointer to the SDL_AssertData structure corresponding to the current assertion.
userdatawhat was passed as userdata to SetAssertionHandler().
Returns
an SDL_AssertState value indicating how to handle the failure.
Thread safety:
This callback may be called from any thread that triggers an assert at any time.
Since
This datatype is available since SDL 3.2.0.

◆ AssertionHandlerCB

using SDL::AssertionHandlerCB = typedef std::function<SDL_AssertState(const SDL_AssertData*)>
Parameters
dataa pointer to the AssertData structure corresponding to the current assertion.
Returns
an AssertState value indicating how to handle the failure.
Thread safety:
This callback may be called from any thread that triggers an assert at any time.
Since
This datatype is available since SDL 3.2.0.
See also
AssertionHandler

◆ AssertState

using SDL::AssertState = typedef SDL_AssertState

When an enabled assertion triggers, it may call the assertion handler (possibly one provided by the app via SDL_SetAssertionHandler), which will return one of these values, possibly after asking the user.

Then SDL will respond based on this outcome (loop around to retry the condition, try to break in a debugger, kill the program, or ignore the problem).

Since
This enum is available since SDL 3.2.0.

Function Documentation

◆ GetAssertionHandler() [1/2]

AssertionHandlerCB SDL::GetAssertionHandler ( )
inline

This returns the function pointer that is called when an assertion is triggered. This is either the value last passed to SDL_SetAssertionHandler(), or if no application-specified function is set, is equivalent to calling SDL_GetDefaultAssertionHandler().

The parameter puserdata is a pointer to a void*, which will store the "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value will always be nullptr for the default handler. If you don't care about this data, it is safe to pass a nullptr pointer to this function to ignore it.

Returns
the AssertionHandlerCB that is called when an assert triggers.
Thread safety:
It is safe to call this function from any thread.
Since
This function is available since SDL 3.2.0.
See also
SetAssertionHandler

◆ GetAssertionHandler() [2/2]

AssertionHandler SDL::GetAssertionHandler ( void **  puserdata)
inline

This returns the function pointer that is called when an assertion is triggered. This is either the value last passed to SDL_SetAssertionHandler(), or if no application-specified function is set, is equivalent to calling GetDefaultAssertionHandler().

The parameter puserdata is a pointer to a void*, which will store the "userdata" pointer that was passed to SetAssertionHandler(). This value will always be nullptr for the default handler. If you don't care about this data, it is safe to pass a nullptr pointer to this function to ignore it.

Parameters
puserdatapointer which is filled with the "userdata" pointer that was passed to SetAssertionHandler().
Returns
the AssertionHandler that is called when an assert triggers.
Thread safety:
It is safe to call this function from any thread.
Since
This function is available since SDL 3.2.0.
See also
SetAssertionHandler

◆ GetAssertionReport()

const AssertData * SDL::GetAssertionReport ( )
inline

This function gets all assertions triggered since the last call to SDL_ResetAssertionReport(), or the start of the program.

The proper way to examine this data looks something like this:

const SDL_AssertData *item = SDL_GetAssertionReport();
while (item) {
printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\@n",
item->condition, item->function, item->filename,
item->linenum, item->trigger_count,
item->always_ignore ? "yes" : "no");
item = item->next;
}
Returns
a list of all failed assertions or nullptr if the list is empty. This memory should not be modified or freed by the application. This pointer remains valid until the next call to Quit() or ResetAssertionReport().
Thread safety:
This function is not thread safe. Other threads calling SDL_ResetAssertionReport() simultaneously, may render the returned pointer invalid.
Since
This function is available since SDL 3.2.0.
See also
SDL_ResetAssertionReport

◆ GetDefaultAssertionHandler()

AssertionHandler SDL::GetDefaultAssertionHandler ( )
inline

This returns the function pointer that is called by default when an assertion is triggered. This is an internal function provided by SDL, that is used for assertions when SetAssertionHandler() hasn't been used to provide a different function.

Returns
the default AssertionHandler that is called when an assert triggers.
Thread safety:
It is safe to call this function from any thread.
Since
This function is available since SDL 3.2.0.
See also
GetAssertionHandler

◆ ReportAssertion()

AssertState SDL::ReportAssertion ( AssertData data,
StringParam  func,
StringParam  file,
int  line 
)
inline

Use the SDL_assert macros instead.

Parameters
dataassert data structure.
funcfunction name.
filefile name.
lineline number.
Returns
assert state.
Thread safety:
It is safe to call this function from any thread.
Since
This function is available since SDL 3.2.0.

◆ ResetAssertionReport()

void SDL::ResetAssertionReport ( )
inline

This function will clear the list of all assertions triggered up to that point. Immediately following this call, SDL_GetAssertionReport will return no items. In addition, any previously-triggered assertions will be reset to a trigger_count of zero, and their always_ignore state will be false.

Thread safety:
This function is not thread safe. Other threads triggering an assertion, or simultaneously calling this function may cause memory leaks or crashes.
Since
This function is available since SDL 3.2.0.
See also
SDL_GetAssertionReport

◆ SetAssertionHandler() [1/2]

void SDL::SetAssertionHandler ( AssertionHandler  handler,
void *  userdata 
)
inline

This function allows an application to show its own assertion UI and/or force the response to an assertion failure. If the application doesn't provide this, SDL will try to do the right thing, popping up a system-specific GUI dialog, and probably minimizing any fullscreen windows.

This callback may fire from any thread, but it runs wrapped in a mutex, so it will only fire from one thread at a time.

This callback is NOT reset to SDL's internal handler upon Quit()!

Parameters
handlerthe SDL_AssertionHandler function to call when an assertion fails or nullptr for the default handler.
userdataa pointer that is passed to handler.
Thread safety:
It is safe to call this function from any thread.
Since
This function is available since SDL 3.2.0.
See also
GetAssertionHandler

◆ SetAssertionHandler() [2/2]

void SDL::SetAssertionHandler ( AssertionHandlerCB  handler)
inline

This function allows an application to show its own assertion UI and/or force the response to an assertion failure. If the application doesn't provide this, SDL will try to do the right thing, popping up a system-specific GUI dialog, and probably minimizing any fullscreen windows.

This callback may fire from any thread, but it runs wrapped in a mutex, so it will only fire from one thread at a time.

This callback is NOT reset to SDL's internal handler upon SDL_Quit()!

Parameters
handlerthe SDL_AssertionHandler function to call when an assertion fails.
Thread safety:
It is safe to call this function from any thread.
Since
This function is available since SDL 3.2.0.
See also
GetAssertionHandler