-
Notifications
You must be signed in to change notification settings - Fork 8
Debugging and logging with A5
This page should be moved to 'tutorials' or 'documentation'.
Hello all!
Here's my fancy new guide to debugging and logging questions about Allegro 5. Consider this the FAQ or a supplement or whatever you like. I'm tired of answering the same questions over and over so now I can point them to this FAQ. ;)
To enable logging of allegro's runtime messages, you need to use either the debugging version or the release version with debugging symbols. When building with CMake, these are specified by -DCMAKE_BUILD_TYPE = {Debug | Release | RelWithDebInfo}
You can also enable the log by using allegro's config routines. If you don't use Allegro5.cfg next to your executable, you can set the system config before initializing allegro instead :
al_set_config_value(al_get_system_config(), "trace", "level", "debug")
Otherwise, in allegro5.cfg, add the following lines under the [trace] section :
level = debug
See the example allegro5.cfg file that comes with allegro for examples of usage.
You can also customize where the trace output goes by using al_register_trace_handler(). It takes a void (*handler)(char const *)
function pointer as an argument, which means you need to provide a function that takes a const char*
and logs it to your output file for example.
By default, allegro's debugging tools aren't that useful. Here I'll show you how to leverage them to get the most out of your debugging experience.
First off, when allegro triggers an assert, all you get is some cryptic output about an expression inside allegro and then your program terminates. What we really need is a backtrace and the stack at the time of the failure. This is where al_register_assert_handler() comes in. You need to pass it a function with the signature void (*handler)(char const *expr, char const *file, int line, char const *func)
.
To give the debugger something to catch, we will intentionally divide by zero. Pretty much every debugger out there will catch the error. Here is an example function we can use to log the details and trigger the error :
void CrashAndBurn(char const *expr, char const *file, int line, char const *func) {
fprintf(stdout , "Expression (%s) failed on line %d of file %s in function %s\n" , expr , line , file , func);
int i = 1/0;/// Ignore the warning we're doing this on purpose
}
Now we just register our handler : al_register_assert_handler(CrashAndBurn);
And voila, now when we run our program in a debugger, and allegro triggers an assert, the debugger catches the crash and we can get a backtrace!
If your game only supports Windows, you can also use Windows-specific function __debugbreak to acheive same result without dividing by zero.
This section soon to come!
Quick Reference for common GDB commands :
gdb myprog.exe set args "arg1" "arg2" etc... run BOOM! CRASH! backtrace backtrace 1 full backtrace full info threads thread apply all bt thread NUM (switch to thread #NUM) bt (backtrace) frame NUM (switch to frame #NUM) p var (print the value of variable var) next step break SourceFile.cpp:123 (set a breakpoint in SourceFile.cpp on line 123) delete 1 (delete breakpoint 1) delete (delete all breakpoints) continue (keep going until the next breakpoint)