[MUD-Dev] Re: Technical C/C++ coding question

Finn Arne Gangstad finnag at guardian.no
Sat Jul 25 09:27:07 CEST 1998


On Sat, 13 Jun 1998, Ben Greear wrote:
> 
> Java has this nice feature called printStackTrace(), that allows
> you to get a stack trace (and log it or whatever) during runtime.

Sorry to answer so late, but here are some functions i made for the
mud I'm working on to do what you want.

stack_trace requires gcc, and will only print a stack-trace containing the
addresses (use gdb or similar to look them up).

const char *
stack_trace()
{
#ifdef __GNUC__
  static char trace_buf[400];
  char *t = trace_buf;
  int m = 1;
  char *p = 0;
  /* The general idea here is that you're not interested in call-trace
   * that goes up above main() */
  const unsigned int delta = size_of_main;
  /* Don't look */
  *t++ = '(';
  m = m && (p = __builtin_return_address(1)) && (t += sprintf(t, "%p", p)) &&
    (p - (char *)main) > delta;
  m = m && (p = __builtin_return_address(2)) && (t += sprintf(t, " %p", p)) &&
    (p - (char *)main) > delta;
  m = m && (p = __builtin_return_address(3)) && (t += sprintf(t, " %p", p)) &&
    (p - (char *)main) > delta;
 /* .... etc as long as you bother (i did it up to 29, if you extend it
  * increase the size of trace_buf */
  *t++ = ')';
  *t++ = 0;
  return trace_buf;
#else
  return "(no stack-trace using this compiler)";
#endif
}

To initialise the global variable "size_of_main", do this in main():

int main(int argc, char **argv)
{
  /* ... */
  size_of_main = (char *)&&main_end - (char *)main;

  /* ... */

main_end:
  exit(0);
}
  

> Is there a way to (easily) do that in c++ as well?  Can I make it
> dump a core file and yet still keep runing?


And here is a function to fork and dump core:

void
fork_and_dump_core(const char *why)
{
    pid_t pid;
    fprintf(stderr, "DEBUG: fork_and_dump_core: %s", why);
    fflush(NULL); /* flush all streams so fork doesn't mess things up */
    pid = fork();
    if (pid == -1) {
        perror("fork_and_dump_core: fork failed");
    } else if (pid == 0) {
        volatile int n = 0; 
        n = 1 / n; /* die horribly */ 
        _exit(0);
    } else {
       waitpid(pid, 0, 0); /* wait for the core dump.. usefulness questioned */
    }
}


The reason for using "1 / n" (where n is 0) to die instead of abort(), is
that abort() didn't include the last function in the call-trace on the OS
i tested it on.

- Finn Arne





More information about the mud-dev-archive mailing list