www.delorie.com/archives/browse.cgi   search  
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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019