GB_ASSERT prints call stack
This commit is contained in:
parent
9c169017d1
commit
3addf42948
|
@ -5,7 +5,7 @@ gb single-file public domain libraries for C & C++
|
||||||
library | latest version | category | languages | description
|
library | latest version | category | languages | description
|
||||||
----------------|----------------|----------|-----------|-------------
|
----------------|----------------|----------|-----------|-------------
|
||||||
**gb_string.h** | 0.93 | strings | C, C++ | A better string library for C & C++
|
**gb_string.h** | 0.93 | strings | C, C++ | A better string library for C & C++
|
||||||
**gb.hpp** | 0.28 | misc | C++11 | (Experimental) A C++11 helper library without STL geared towards game development
|
**gb.hpp** | 0.29 | misc | C++11 | (Experimental) A C++11 helper library without STL geared towards game development
|
||||||
**gb_math.hpp** | 0.03a | math | C++11 | A C++11 math library geared towards game development
|
**gb_math.hpp** | 0.03a | math | C++11 | A C++11 math library geared towards game development
|
||||||
**gb_ini.h** | 0.91a | misc | C, C++ | A simple ini file loader library for C & C++
|
**gb_ini.h** | 0.91a | misc | C, C++ | A simple ini file loader library for C & C++
|
||||||
|
|
||||||
|
|
245
gb.hpp
245
gb.hpp
|
@ -1,4 +1,4 @@
|
||||||
// gb.hpp - v0.27 - public domain C++11 helper library - no warranty implied; use at your own risk
|
// gb.hpp - v0.29 - public domain C++11 helper library - no warranty implied; use at your own risk
|
||||||
// (Experimental) A C++11 helper library without STL geared towards game development
|
// (Experimental) A C++11 helper library without STL geared towards game development
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -37,6 +37,50 @@ CONTENTS:
|
||||||
- Hash Functions
|
- Hash Functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Version History:
|
||||||
|
0.29 - GB_ASSERT prints call stack
|
||||||
|
0.28 - Pool Allocator
|
||||||
|
0.27 - Dealloc to Free & More Hashing Functions
|
||||||
|
0.26a - Heap_Allocator Fix
|
||||||
|
0.26 - Better Allocation system
|
||||||
|
0.25a - Array bug fix
|
||||||
|
0.25 - Faster Heap_Allocator for Windows using HeapAlloc
|
||||||
|
0.24b - Even More Hash_Table Bug Fixes
|
||||||
|
0.24a - Hash_Table Bug Fixes
|
||||||
|
0.24 - More documentation and bug fixes
|
||||||
|
0.23 - Move Semantics for Array and Hash_Table
|
||||||
|
0.22 - Code rearrangment into namespaces
|
||||||
|
0.21d - Fix array::free
|
||||||
|
0.21c - Fix Another Typo causing unresolved external symbol
|
||||||
|
0.21b - Typo fixes
|
||||||
|
0.21a - Better `static` keywords
|
||||||
|
0.21 - Separate Math Library
|
||||||
|
0.20a - #ifndef for many macros
|
||||||
|
0.20 - Angle
|
||||||
|
0.19 - Cache friendly Transform and String fixes
|
||||||
|
0.18 - Hash_Table bug fixes
|
||||||
|
0.17 - Death to OOP
|
||||||
|
0.16 - All References are const convention
|
||||||
|
0.15 - Namespaced Types
|
||||||
|
0.14 - Casts and Quaternion Look At
|
||||||
|
0.13a - Fix Todos
|
||||||
|
0.13 - Basic Type Traits
|
||||||
|
0.12 - Random
|
||||||
|
0.11 - Complex
|
||||||
|
0.10 - Atomics
|
||||||
|
0.09 - Bug Fixes
|
||||||
|
0.08 - Matrix(2,3)
|
||||||
|
0.07 - Bug Fixes
|
||||||
|
0.06 - Os spec ideas
|
||||||
|
0.05 - Transform Type and Quaternion Functions
|
||||||
|
0.04 - String
|
||||||
|
0.03 - Hash Functions
|
||||||
|
0.02 - Hash Table
|
||||||
|
0.01 - Initial Version
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef GB_INCLUDE_GB_HPP
|
#ifndef GB_INCLUDE_GB_HPP
|
||||||
#define GB_INCLUDE_GB_HPP
|
#define GB_INCLUDE_GB_HPP
|
||||||
|
|
||||||
|
@ -146,7 +190,7 @@ CONTENTS:
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO(bill): Check if this KEPLER_ENVIRONMENT works on clang
|
// TODO(bill): Check if this works on clang
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#if defined(__x86_64__) || defined(__ppc64__)
|
#if defined(__x86_64__) || defined(__ppc64__)
|
||||||
#ifndef GB_ARCH_64_BIT
|
#ifndef GB_ARCH_64_BIT
|
||||||
|
@ -239,40 +283,18 @@ CONTENTS:
|
||||||
Type& operator=(Type&&) = delete
|
Type& operator=(Type&&) = delete
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(GB_ASSERT)
|
#if !defined(GB_ASSERT)
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
#define GB_ASSERT(x, ...) ((void)(::gb__assert_handler((x), #x, __FILE__, __LINE__, ##__VA_ARGS__)))
|
#define GB_ASSERT(x, ...) ((void)(::gb__assert_handler((x), #x, __FILE__, __LINE__, ##__VA_ARGS__)))
|
||||||
|
|
||||||
// Helper function used as a better alternative to assert which allows for
|
// Helper function used as a better alternative to assert which allows for
|
||||||
// optional printf style error messages
|
// optional printf style error messages
|
||||||
extern "C" inline void
|
extern "C" void
|
||||||
gb__assert_handler(bool condition, const char* condition_str,
|
gb__assert_handler(bool condition, const char* condition_str,
|
||||||
const char* filename, size_t line,
|
const char* filename, size_t line,
|
||||||
const char* error_text = nullptr, ...)
|
const char* error_text = nullptr, ...);
|
||||||
{
|
|
||||||
if (condition)
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr, "ASSERT! %s(%lu): %s", filename, line, condition_str);
|
|
||||||
if (error_text)
|
|
||||||
{
|
|
||||||
fprintf(stderr, " - ");
|
|
||||||
|
|
||||||
va_list args;
|
|
||||||
va_start(args, error_text);
|
|
||||||
vfprintf(stderr, error_text, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
#if defined(GB_COMPILER_MSVC)
|
|
||||||
__debugbreak();
|
|
||||||
#elif defined(GB_COMPILER_GNU_GCC)
|
|
||||||
__builtin_trap();
|
|
||||||
#else
|
|
||||||
#error Implement aborting function
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define GB_ASSERT(x, ...) ((void)sizeof(x))
|
#define GB_ASSERT(x, ...) ((void)sizeof(x))
|
||||||
|
@ -2231,8 +2253,133 @@ __GB_NAMESPACE_END
|
||||||
// Implemenation //
|
// Implemenation //
|
||||||
// //
|
// //
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
#if defined(GB_IMPLEMENTATION)
|
#if defined(GB_IMPLEMENTATION)
|
||||||
__GB_NAMESPACE_START
|
__GB_NAMESPACE_START
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
|
||||||
|
#include <dbghelp.h>
|
||||||
|
#pragma comment(lib, "dbghelp.lib")
|
||||||
|
|
||||||
|
internal_linkage void
|
||||||
|
gb__print_call_stack(FILE* out_stream)
|
||||||
|
{
|
||||||
|
SymInitialize(GetCurrentProcess(), nullptr, true);
|
||||||
|
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
|
||||||
|
|
||||||
|
DWORD mtype = {};
|
||||||
|
CONTEXT ctx = {};
|
||||||
|
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||||
|
|
||||||
|
RtlCaptureContext(&ctx);
|
||||||
|
|
||||||
|
STACKFRAME64 stack = {};
|
||||||
|
|
||||||
|
#if defined(_M_IX86)
|
||||||
|
mtype = IMAGE_FILE_MACHINE_I386;
|
||||||
|
stack.AddrPC.Offset = ctx.Eip;
|
||||||
|
stack.AddrPC.Mode = AddrModeFlat;
|
||||||
|
stack.AddrFrame.Offset = ctx.Ebp;
|
||||||
|
stack.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
stack.AddrStack.Offset = ctx.Esp;
|
||||||
|
stack.AddrStack.Mode = AddrModeFlat;
|
||||||
|
#elif defined(_M_X64)
|
||||||
|
mtype = IMAGE_FILE_MACHINE_AMD64;
|
||||||
|
stack.AddrPC.Offset = ctx.Rip;
|
||||||
|
stack.AddrPC.Mode = AddrModeFlat;
|
||||||
|
stack.AddrFrame.Offset = ctx.Rsp;
|
||||||
|
stack.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
stack.AddrStack.Offset = ctx.Rsp;
|
||||||
|
stack.AddrStack.Mode = AddrModeFlat;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DWORD ldsp = 0;
|
||||||
|
IMAGEHLP_LINE64 line = {};
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
|
||||||
|
char buf[sizeof(SYMBOL_INFO) + (MAX_SYM_NAME * sizeof(TCHAR))];
|
||||||
|
|
||||||
|
SYMBOL_INFO* sym = reinterpret_cast<SYMBOL_INFO*>(buf);
|
||||||
|
sym->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
sym->MaxNameLen = MAX_SYM_NAME;
|
||||||
|
|
||||||
|
UINT layer_count = 0;
|
||||||
|
while (StackWalk64(mtype,
|
||||||
|
GetCurrentProcess(), GetCurrentThread(),
|
||||||
|
&stack, &ctx, nullptr,
|
||||||
|
SymFunctionTableAccess64, SymGetModuleBase64, nullptr))
|
||||||
|
{
|
||||||
|
if (stack.AddrPC.Offset == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
BOOL result = SymGetLineFromAddr64(GetCurrentProcess(), stack.AddrPC.Offset, &ldsp, &line);
|
||||||
|
result = result && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
fprintf(out_stream,
|
||||||
|
"\t[%u] `%s` (%s:%d)\n",
|
||||||
|
layer_count, sym->Name, line.FileName, line.LineNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(out_stream,
|
||||||
|
"\t[%u] 0x%p\n",
|
||||||
|
layer_count, stack.AddrPC.Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymCleanup(GetCurrentProcess());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error gb__print_call_stack() not implemeneted
|
||||||
|
// TODO(bill): Implemenet gb__print_call_stack()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Helper function used as a better alternative to assert which allows for
|
||||||
|
// optional printf style error messages
|
||||||
|
inline void
|
||||||
|
gb__assert_handler(bool condition, const char* condition_str,
|
||||||
|
const char* filename, size_t line,
|
||||||
|
const char* error_text, ...)
|
||||||
|
{
|
||||||
|
if (condition)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FILE* out_stream = stderr;
|
||||||
|
|
||||||
|
fprintf(out_stream, "ASSERT! %s(%lu): %s", filename, line, condition_str);
|
||||||
|
if (error_text)
|
||||||
|
{
|
||||||
|
fprintf(out_stream, " - ");
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, error_text);
|
||||||
|
vfprintf(out_stream, error_text, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
fprintf(out_stream, "\n");
|
||||||
|
|
||||||
|
fprintf(out_stream, "Stacktrack:\n");
|
||||||
|
gb__print_call_stack(out_stream);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO(bill): Are these decent breaking functions???
|
||||||
|
#if defined(GB_COMPILER_MSVC)
|
||||||
|
__debugbreak();
|
||||||
|
#elif defined(GB_COMPILER_GNU_GCC)
|
||||||
|
__builtin_trap();
|
||||||
|
#else
|
||||||
|
#error Implement aborting function
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// //
|
// //
|
||||||
// Memory //
|
// Memory //
|
||||||
|
@ -4143,45 +4290,3 @@ rdtsc()
|
||||||
__GB_NAMESPACE_END
|
__GB_NAMESPACE_END
|
||||||
|
|
||||||
#endif // GB_IMPLEMENTATION
|
#endif // GB_IMPLEMENTATION
|
||||||
|
|
||||||
/*
|
|
||||||
Version History:
|
|
||||||
0.28 - Pool Allocator
|
|
||||||
0.27 - Dealloc to Free & More Hashing Functions
|
|
||||||
0.26a - Heap_Allocator Fix
|
|
||||||
0.26 - Better Allocation system
|
|
||||||
0.25a - Array bug fix
|
|
||||||
0.25 - Faster Heap_Allocator for Windows using HeapAlloc
|
|
||||||
0.24b - Even More Hash_Table Bug Fixes
|
|
||||||
0.24a - Hash_Table Bug Fixes
|
|
||||||
0.24 - More documentation and bug fixes
|
|
||||||
0.23 - Move Semantics for Array and Hash_Table
|
|
||||||
0.22 - Code rearrangment into namespaces
|
|
||||||
0.21d - Fix array::free
|
|
||||||
0.21c - Fix Another Typo causing unresolved external symbol
|
|
||||||
0.21b - Typo fixes
|
|
||||||
0.21a - Better `static` keywords
|
|
||||||
0.21 - Separate Math Library
|
|
||||||
0.20a - #ifndef for many macros
|
|
||||||
0.20 - Angle
|
|
||||||
0.19 - Cache friendly Transform and String fixes
|
|
||||||
0.18 - Hash_Table bug fixes
|
|
||||||
0.17 - Death to OOP
|
|
||||||
0.16 - All References are const convention
|
|
||||||
0.15 - Namespaced Types
|
|
||||||
0.14 - Casts and Quaternion Look At
|
|
||||||
0.13a - Fix Todos
|
|
||||||
0.13 - Basic Type Traits
|
|
||||||
0.12 - Random
|
|
||||||
0.11 - Complex
|
|
||||||
0.10 - Atomics
|
|
||||||
0.09 - Bug Fixes
|
|
||||||
0.08 - Matrix(2,3)
|
|
||||||
0.07 - Bug Fixes
|
|
||||||
0.06 - Os spec ideas
|
|
||||||
0.05 - Transform Type and Quaternion Functions
|
|
||||||
0.04 - String
|
|
||||||
0.03 - Hash Functions
|
|
||||||
0.02 - Hash Table
|
|
||||||
0.01 - Initial Version
|
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue