Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3627158
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T23:51:10+00:00 2026-05-18T23:51:10+00:00

Using a function like this: #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <unistd.h> void

  • 0

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?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T23:51:11+00:00Added an answer on May 18, 2026 at 11:51 pm

    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:

    • Method #1:

    The first method is to disseminate it
    with print and log messages in order
    to pinpoint the execution path. In a
    complex program, this option can
    become cumbersome and tedious even if,
    with the help of some GCC-specific
    macros, it can be simplified a bit.
    Consider, for example, a debug macro
    such as:

     #define TRACE_MSG fprintf(stderr, __FUNCTION__     \
                              "() [%s:%d] here I am\n", \
                              __FILE__, __LINE__)
    

    You can propagate this macro quickly
    throughout your program by cutting and
    pasting it. When you do not need it
    anymore, switch it off simply by
    defining it to no-op.

    • Method #2: (It doesn’t say anything about line numbers, but I do on method 4)

    A nicer way to get a stack backtrace,
    however, is to use some of the
    specific support functions provided by
    glibc. The key one is backtrace(),
    which navigates the stack frames from
    the calling point to the beginning of
    the program and provides an array of
    return addresses. You then can map
    each address to the body of a
    particular function in your code by
    having a look at the object file with
    the nm command. Or, you can do it a
    simpler way–use backtrace_symbols().
    This function transforms a list of
    return addresses, as returned by
    backtrace(), into a list of strings,
    each containing the function name
    offset within the function and the
    return address. The list of strings is
    allocated from your heap space (as if
    you called malloc()), so you should
    free() it as soon as you are done with
    it.

    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.

    • Method #3: (A better way of doing method 2)

    An even more useful application for
    this technique is putting a stack
    backtrace inside a signal handler and
    having the latter catch all the “bad”
    signals your program can receive
    (SIGSEGV, SIGBUS, SIGILL, SIGFPE and
    the like). This way, if your program
    unfortunately crashes and you were not
    running it with a debugger, you can
    get a stack trace and know where the
    fault happened. This technique also
    can be used to understand where your
    program is looping in case it stops
    responding

    An implementation of this technique is available here.

    • Method #4:

    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

    convert addresses into file names and
    line numbers.

    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 ??:0 instead of file names.

    #include <stdio.h>
    #include <signal.h>
    #include <stdio.h>
    #include <signal.h>
    #include <execinfo.h>
    
    void bt_sighandler(int sig, struct sigcontext ctx) {
    
      void *trace[16];
      char **messages = (char **)NULL;
      int i, trace_size = 0;
    
      if (sig == SIGSEGV)
        printf("Got signal %d, faulty address is %p, "
               "from %p\n", sig, ctx.cr2, ctx.eip);
      else
        printf("Got signal %d\n", sig);
    
      trace_size = backtrace(trace, 16);
      /* overwrite sigaction with caller's address */
      trace[1] = (void *)ctx.eip;
      messages = backtrace_symbols(trace, trace_size);
      /* skip first stack frame (points here) */
      printf("[bt] Execution path:\n");
      for (i=1; i<trace_size; ++i)
      {
        printf("[bt] #%d %s\n", i, messages[i]);
    
        /* find first occurence of '(' or ' ' in message[i] and assume
         * everything before that is the file name. (Don't go beyond 0 though
         * (string terminator)*/
        size_t p = 0;
        while(messages[i][p] != '(' && messages[i][p] != ' '
                && messages[i][p] != 0)
            ++p;
    
        char syscom[256];
        sprintf(syscom,"addr2line %p -e %.*s", trace[i], p, messages[i]);
            //last parameter is the file name of the symbol
        system(syscom);
      }
    
      exit(0);
    }
    
    
    int func_a(int a, char b) {
    
      char *p = (char *)0xdeadbeef;
    
      a = a + b;
      *p = 10;  /* CRASH here!! */
    
      return 2*a;
    }
    
    
    int func_b() {
    
      int res, a = 5;
    
      res = 5 + func_a(a, 't');
    
      return res;
    }
    
    
    int main() {
    
      /* Install our signal handler */
      struct sigaction sa;
    
      sa.sa_handler = (void *)bt_sighandler;
      sigemptyset(&sa.sa_mask);
      sa.sa_flags = SA_RESTART;
    
      sigaction(SIGSEGV, &sa, NULL);
      sigaction(SIGUSR1, &sa, NULL);
      /* ... add any other signal here */
    
      /* Do something */
      printf("%d\n", func_b());
    }
    

    This code should be compiled as: gcc sighandler.c -o sighandler -rdynamic

    The program outputs:

    Got signal 11, faulty address is 0xdeadbeef, from 0x8048975
    [bt] Execution path:
    [bt] #1 ./sighandler(func_a+0x1d) [0x8048975]
    /home/karl/workspace/stacktrace/sighandler.c:44
    [bt] #2 ./sighandler(func_b+0x20) [0x804899f]
    /home/karl/workspace/stacktrace/sighandler.c:54
    [bt] #3 ./sighandler(main+0x6c) [0x8048a16]
    /home/karl/workspace/stacktrace/sighandler.c:74
    [bt] #4 /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0x3fdbd6]
    ??:0
    [bt] #5 ./sighandler() [0x8048781]
    ??:0
    

    Update 2012/04/28 for recent linux kernel versions, the above sigaction signature is obsolete. Also I improved it a bit by grabbing the executable name from this answer. Here is an up to date version:

    char* exe = 0;
    
    int initialiseExecutableName() 
    {
        char link[1024];
        exe = new char[1024];
        snprintf(link,sizeof link,"/proc/%d/exe",getpid());
        if(readlink(link,exe,sizeof link)==-1) {
            fprintf(stderr,"ERRORRRRR\n");
            exit(1);
        }
        printf("Executable name initialised: %s\n",exe);
    }
    
    const char* getExecutableName()
    {
        if (exe == 0)
            initialiseExecutableName();
        return exe;
    }
    
    /* get REG_EIP from ucontext.h */
    #define __USE_GNU
    #include <ucontext.h>
    
    void bt_sighandler(int sig, siginfo_t *info,
                       void *secret) {
    
      void *trace[16];
      char **messages = (char **)NULL;
      int i, trace_size = 0;
      ucontext_t *uc = (ucontext_t *)secret;
    
      /* Do something useful with siginfo_t */
      if (sig == SIGSEGV)
        printf("Got signal %d, faulty address is %p, "
               "from %p\n", sig, info->si_addr, 
               uc->uc_mcontext.gregs[REG_EIP]);
      else
        printf("Got signal %d\n", sig);
    
      trace_size = backtrace(trace, 16);
      /* overwrite sigaction with caller's address */
      trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
    
      messages = backtrace_symbols(trace, trace_size);
      /* skip first stack frame (points here) */
      printf("[bt] Execution path:\n");
      for (i=1; i<trace_size; ++i)
      {
        printf("[bt] %s\n", messages[i]);
    
        /* find first occurence of '(' or ' ' in message[i] and assume
         * everything before that is the file name. (Don't go beyond 0 though
         * (string terminator)*/
        size_t p = 0;
        while(messages[i][p] != '(' && messages[i][p] != ' '
                && messages[i][p] != 0)
            ++p;
    
        char syscom[256];
        sprintf(syscom,"addr2line %p -e %.*s", trace[i] , p, messages[i] );
               //last parameter is the filename of the symbol
        system(syscom);
    
      }
      exit(0);
    }
    

    and initialise like this:

    int main() {
    
      /* Install our signal handler */
      struct sigaction sa;
    
      sa.sa_sigaction = (void *)bt_sighandler;
      sigemptyset (&sa.sa_mask);
      sa.sa_flags = SA_RESTART | SA_SIGINFO;
    
      sigaction(SIGSEGV, &sa, NULL);
      sigaction(SIGUSR1, &sa, NULL);
      /* ... add any other signal here */
    
      /* Do something */
      printf("%d\n", func_b());
    
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a function using strtok like this void f1(char *name) { ... char
I easily get Week Number using MySql Week function like this WEEK(SYSDATE()) I just
I'm using openURL to send an email w/some links. The function looks like this:
I have put together an image scroller using jquery, like this function rotateImages(whichHolder, start)
Using javascript I'm looping through my H3 elements like this: $('h3').each(function(){ }); I'm then
I'm using Expressjs w/ node.js and I have a route like this: users.init(app.db, function()
Using jQuery on() version 1.7. I bind my events usually like this: $(.foo).on(click, function()
I am uploading image using filedrop.js. Code in application.js file looks like this:- $(.droparea).each(function(event){
I'm using a code that looks like that: img.load(function(){ // do some stuff $(this).width();
I wrote this code in C: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.