2020#include < set>
2121#include < numeric>
2222#include < map>
23+ #include < unistd.h>
2324using namespace std ;
2425using ll = long long int ;
2526
@@ -41,14 +42,49 @@ using ll = long long int;
4142void assert_with_backtrace (bool condition, std::string error_msg=" " ) {
4243 if (!condition) {
4344 void * callstack[256 ];
44- int i, frames = backtrace (callstack, 256 );
45- char ** strs = backtrace_symbols (callstack, frames);
46- for (i = 0 ; i < frames; ++i) {
47- fprintf (stderr, " %s\n " , strs[i]);
45+ int frames = backtrace (callstack, 256 );
46+
47+ // get executable path
48+ char exec_path[1024 ] = {0 };
49+ ssize_t len = readlink (" /proc/self/exe" , exec_path, sizeof (exec_path) - 1 );
50+ if (len == -1 ) {
51+ strcpy (exec_path, " ./a.out" );
52+ } else {
53+ exec_path[len] = ' \0 ' ;
54+ }
55+
56+ // build addr2line command
57+ std::string cmd = " addr2line -e " ;
58+ cmd += exec_path;
59+ cmd += " -f -C" ; // -f for function names, -C for demangling
60+
61+ for (int i = 0 ; i < frames; ++i) {
62+ char addr_str[32 ];
63+ sprintf (addr_str, " %p" , callstack[i]);
64+ cmd += addr_str;
65+ }
66+
67+ fprintf (stderr, " Assertion failed. Stack trace:\n " );
68+ FILE* pipe = popen (cmd.c_str (), " r" );
69+ if (!pipe) {
70+ fprintf (stderr, " Failed to run addr2line. Falling back to backtrace_symbols.\n " );
71+ char ** strs = backtrace_symbols (callstack, frames);
72+ for (int i = 0 ; i < frames; ++i) {
73+ fprintf (stderr, " %s\n " , strs[i]);
74+ }
75+ free (strs);
76+ } else {
77+ char buffer[512 ];
78+ while (fgets (buffer, sizeof (buffer), pipe) != nullptr ) {
79+ fprintf (stderr, " %s" , buffer);
80+ }
81+ pclose (pipe);
82+ }
83+
84+ if (!error_msg.empty ()) {
85+ fprintf (stderr, " \n Error: %s\n " , error_msg.c_str ());
4886 }
49- free (strs);
50- fprintf (stderr, " %s\n " , error_msg.c_str ());
51- ASSERT (false );
87+ exit (1 );
5288 }
5389}
5490
0 commit comments