Mail Archives: djgpp/1996/06/14/19:03:49
Xref: | news2.mv.net comp.os.msdos.djgpp:4974
|
From: | Roland Exler <R DOT Exler AT jk DOT uni-linz DOT ac DOT at>
|
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
|
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<assert.h> to
#include<t_assert.h> (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 <stdio.h>
#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<y */
fprintf(stderr, "Assertion failed at %s line %d: %s\n", file, line, msg);
asm ("int $3");
exit(1);
}
====================== file no_sig.c =========================
/* test of abort() and assert() with stack-trace _NOT_ using signals */
#include <stdio.h>
#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 <stdio.h>
#include <signal.h>
#include <assert.h>
/* (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
+---------------------------------------+---------------------------+
- Raw text -