Using a function like this:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
void print_trace() {
char pid_buf[30];
sprintf(pid_buf, "--pid=%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
int child_pid = fork();
if (!child_pid) {
dup2(2,1); // redirect output to stderr
fprintf(stdout,"stack trace for %s pid=%s\n",name_buf,pid_buf);
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
abort(); /* If gdb failed to start */
} else {
waitpid(child_pid,NULL,0);
}
}
I see the details of print_trace in the output.
What are other ways to do it?
You mentioned on my other answer (now deleted) that you also want to see line numbers. I’m not sure how to do that when invoking gdb from inside your application.
But I’m going to share with you a couple of ways to print a simple stacktrace with function names and their respective line numbers without using gdb. Most of them came from a very nice article from Linux Journal:
I encourage you to read it since the page has source code examples. In order to convert an address to a function name you must compile your application with the -rdynamic option.
An implementation of this technique is available here.
A small improvement I’ve done on method #3 to print line numbers. This could be copied to work on method #2 also.
Basically, I followed a tip that uses addr2line to
The source code below prints line numbers for all local functions. If a function from another library is called, you might see a couple of
??:0instead of file names.This code should be compiled as:
gcc sighandler.c -o sighandler -rdynamicThe program outputs:
Update 2012/04/28 for recent linux kernel versions, the above
sigactionsignature is obsolete. Also I improved it a bit by grabbing the executable name from this answer. Here is an up to date version:and initialise like this: