Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
assert.cpp
Go to the documentation of this file.
1#include <helios/core_pch.hpp>
2
4
6
7#ifdef HELIOS_ENABLE_STACKTRACE
8#ifdef HELIOS_USE_STL_STACKTRACE
9#include <stacktrace>
10#else
11#include <boost/stacktrace.hpp>
12#endif
13#endif
14
15#include <cstdio>
16#include <cstdlib>
17#include <source_location>
18#include <string>
19#include <string_view>
20
21namespace helios {
22
23namespace {
24
25#ifdef HELIOS_ENABLE_STACKTRACE
26
27void PrintStackTrace() noexcept {
28 try {
29#ifdef HELIOS_USE_STL_STACKTRACE
30 const std::stacktrace stack_trace = std::stacktrace::current();
31 if (stack_trace.size() > 1) {
32#if defined(__cpp_lib_print) && (__cpp_lib_print >= 202302L)
33 std::println("\nStack trace:");
34 for (size_t i = 1; i < stack_trace.size() && i < 32; ++i) {
35 std::string entry_str = std::to_string(stack_trace[i]);
36 std::println(" {}: {}", i, entry_str);
37 }
38#else
39 std::fprintf(stderr, "\nStack trace:\n");
40 for (size_t i = 1; i < stack_trace.size() && i < 32; ++i) {
41 std::string entry_str = std::to_string(stack_trace[i]);
42 std::fprintf(stderr, " %zu: %s\n", i, entry_str.c_str());
43 }
44#endif
45 } else {
46#if defined(__cpp_lib_print) && (__cpp_lib_print >= 202302L)
47 std::println("\nStack trace: <empty>");
48#else
49 std::fprintf(stderr, "\nStack trace: <empty>\n");
50#endif
51 }
52#else // Use Boost stacktrace
53 const boost::stacktrace::stacktrace stack_trace;
54 if (stack_trace.size() > 1) {
55#if defined(__cpp_lib_print) && (__cpp_lib_print >= 202302L)
56 std::println("\nStack trace:");
57 for (size_t i = 1; i < stack_trace.size() && i < 32; ++i) {
58 std::string entry_str = boost::stacktrace::to_string(stack_trace[i]);
59 std::println(" {}: {}", i, entry_str);
60 }
61#else
62 std::fprintf(stderr, "\nStack trace:\n");
63 for (size_t i = 1; i < stack_trace.size() && i < 32; ++i) {
64 std::string entry_str = boost::stacktrace::to_string(stack_trace[i]);
65 std::fprintf(stderr, " %zu: %s\n", i, entry_str.c_str());
66 }
67#endif
68 } else {
69#if defined(__cpp_lib_print) && (__cpp_lib_print >= 202302L)
70 std::println("\nStack trace: <empty>");
71#else
72 std::fprintf(stderr, "\nStack trace: <empty>\n");
73#endif
74 }
75#endif // HELIOS_USE_STL_STACKTRACE
76 } catch (...) {
77#if defined(__cpp_lib_print) && (__cpp_lib_print >= 202302L)
78 std::println("\nStack trace: <error during capture>");
79#else
80 std::fprintf(stderr, "\nStack trace: <error during capture>\n");
81#endif
82 }
83}
84
85#endif // HELIOS_ENABLE_STACKTRACE
86
87} // namespace
88
89void AbortWithStacktrace(std::string_view message) noexcept {
90#if defined(__cpp_lib_print) && (__cpp_lib_print >= 202302L)
91 // Use std::println when available (C++23)
92 std::println("\n=== FATAL ERROR ===");
93 std::println("Message: {}", message);
94
95#ifdef HELIOS_ENABLE_STACKTRACE
96 PrintStackTrace();
97#else
98 std::println("\nStack trace: <not available - build with HELIOS_ENABLE_STACKTRACE>");
99#endif
100
101 std::println("===================\n");
102 std::fflush(stdout);
103#else
104 // Fallback to fprintf to stderr when std::println is not available
105 std::fprintf(stderr, "\n=== FATAL ERROR ===\n");
106 std::fprintf(stderr, "Message: %.*s\n", static_cast<int>(message.size()), message.data());
107
108#ifdef HELIOS_ENABLE_STACKTRACE
109 PrintStackTrace();
110#else
111 std::fprintf(stderr, "\nStack trace: <not available - build with HELIOS_ENABLE_STACKTRACE>\n");
112#endif
113
114 std::fprintf(stderr, "===================\n\n");
115 std::fflush(stderr);
116#endif
117
119 std::abort();
120}
121
122namespace details {
123
124// Weak symbol stub - will be overridden by logger.hpp inline version if included
125// On MSVC, the definition is provided by logger.cpp, so we skip this fallback
126// On GCC/Clang, we use weak attribute so the inline version from logger.hpp takes precedence
127#if !defined(_MSC_VER)
128#if defined(__GNUC__) || defined(__clang__)
129__attribute__((weak))
130#endif
131void LogAssertionFailureViaLogger([[maybe_unused]] std::string_view condition,
132 [[maybe_unused]] const std::source_location& loc,
133 [[maybe_unused]] std::string_view message) noexcept {
134 // Default implementation does nothing.
135 // The real implementation is provided by logger.hpp when included.
136}
137#endif
138
139} // namespace details
140
141} // namespace helios
#define HELIOS_DEBUG_BREAK()
Definition core.hpp:89
void LogAssertionFailureViaLogger(std::string_view condition, const std::source_location &loc, std::string_view message) noexcept
Bridge to logger-provided assertion logging.
Definition logger.hpp:649
void AbortWithStacktrace(std::string_view message) noexcept
Prints a message with stack trace and aborts the program execution.
Definition assert.cpp:89