Xref: news2.mv.net comp.os.msdos.djgpp:4974 From: Roland Exler Newsgroups: comp.os.msdos.djgpp Subject: stack-trace on abort() and assert()! Date: Tue, 11 Jun 1996 13:11:30 -0700 Organization: Institute for el. Measurement, University of Linz, Austria Lines: 151 Message-ID: <31BDD2F2.3021@jk.uni-linz.ac.at> NNTP-Posting-Host: sensor4.emt.uni-linz.ac.at Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp There was some discussion on getting stack-traces on assert() and abort() for debugging. I've put together all responses and developed two short examples how to do this, one using signals and one without. Both of them print a stack-trace useable by 'symify'. The way without signals has the advantage of not changing the program to install the signal-handler, but needs to change the #include to #include (or replacing assert.h by t_assert.h). Using t_assert.h redefines abort() to print the stack-trace. Using signals, it's neccecary to install a signal-handler for SIGABRT and redefining abort() to raise signal SIGABRT. Warning: the stack-trace is longer using signals! NOTE: as both ways need to redefine abort(), any object-files which should use the new feature must be recomplied. I hope the functions are helpful for many programmers as they have been for me. Send comments to R DOT Exler AT jk DOT uni-linz DOT ac DOT at (I'm not at work till June, 24th, so I'll probably not see your comments if posted to the newsgroup in between. Roland PS: extract files, run make and try running 'test_sig' and 'no_sig'. On exit, use 'symify NAME.exe' to show the source-functions and lines. If you run the test-programs without any argument they exit using abort(), with any argument on the command-line they exit using a false assertion. ====================== file t_assert.h ========================= /* Copyright (C) 1996 Exler Roland, based on 'assert.h' */ /* written by DJ Delorie, see COPYING.DJ for details */ #ifndef __dj_ENFORCE_ANSI_FREESTANDING #if defined(assert) /* leave unchanged if already defined, so asserts may be mixed */ #else /* if not defined, set equal to trace_assert() */ #define assert(test) trace_assert(test) #endif #undef trace_assert /* trace_assert() is always with stack-trace */ #if defined(NDEBUG) #define trace_assert(test) (void)0 #else #define trace_assert(test) ((test)?0:__trace_assert(#test,__FILE__,__LINE__)) #endif #ifndef __dj_include_t_assert_h_ #define __dj_include_t_assert_h_ #ifdef __cplusplus extern "C" { #endif void __trace_assert(const char *,const char *,int) __attribute__ ((noreturn)); /* (re)define abort to get stack-trace */ #undef abort #define abort() asm("int $3") #ifdef __cplusplus } #endif #endif /* !__dj_include_t_assert_h_ */ #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ ====================== file t_assert.c ========================= #include #include "t_assert.h" /* output message like assert() does, force stack-trace */ /* NOTE: function will be called by macro trace_assert() or assert() */ void __trace_assert(const char *msg, const char *file, int line) { /* Assertion failed at foo.c line 45: x #include "t_assert.h" #include "test.cc" int main(int argc) { printf("depth in main()=%d\n",depth()); if (argc>1) try_assert(); else try_abort(); return 0; } ====================== file test_sig.c ========================= /* test of abort() and assert() with stack-trace using signals */ #include #include #include /* (re)define abort() to raise SIGABRT */ #define abort() (raise(SIGABRT)) /* force stack-trace on SIGABRT */ static void __trace_abort(int signo) { asm ("int $3"); } #include "test.cc" int main(int argc) { signal(SIGABRT,__trace_abort); /* register signal-handler for SIGABRT */ printf("depth in main()=%d\n",depth()); if (argc>1) try_assert(); else try_abort(); return 0; } ======================== makefile ============================ ..PHONY: all lib exe clear CFLAGS=-g -O2 -Wall TARGET_ARCH=-m486 all: t_assert.o exe exe: test_sig.exe no_sig.exe t_assert.o: t_assert.c t_assert.h %.exe: %.c test.c t_assert.o $(LINK.c) -o $@ $< t_assert.o clear: del t_assert.o del test_sig.exe del no_sig.exe ============================================================== +---------------------------------------+---------------------------+ I Roland Exler I EMAIL: I I Universitaet Linz I R DOT Exler AT jk DOT uni-linz DOT ac DOT at I I Institut fuer Elektrische Messtechnik I I I Altenbergerstr. 69 I Phone: I I A-4040 Linz, AUSTRIA I + 43 732 2468 9205 I +---------------------------------------+---------------------------+