现在的位置: 首页 > 综合 > 正文

c中如何打印函数调用堆栈? – C/C++ – ChinaUnix.net

2013年05月12日 ⁄ 综合 ⁄ 共 2268字 ⁄ 字号 评论关闭

导读:

试验了一下,好像只能打印出地址,但是有函数名更方便些
在11楼的提示下在网上找了篇文章,自己裁减了一下

//funstack.c
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include #include

#if defined(REG_RIP)
# define SIGSEGV_STACK_IA64
# define REGFORMAT "%016lx"
#elif defined(REG_EIP)
# define SIGSEGV_STACK_X86
# define REGFORMAT "%08x"
#else
# define SIGSEGV_STACK_GENERIC
# define REGFORMAT "%x"
#endif

static void signal_segv(int signum, siginfo_t* info, void*ptr) {
        static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};

        size_t i;
        ucontext_t *ucontext = (ucontext_t*)ptr;

#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
        int f = 0;
        Dl_info dlinfo;
        void **bp = 0;
        void *ip = 0;
#else
        void *bt[20];
        char **strings;
        size_t sz;
#endif

#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
# if defined(SIGSEGV_STACK_IA64)
        ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
        bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
# elif defined(SIGSEGV_STACK_X86)
        ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
        bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
# endif

        fprintf(stderr, "Stack trace:/n");
        while(bp && ip) {
                if(!dladdr(ip, &dlinfo))
                        break;

                const char *symname = dlinfo.dli_sname;

                fprintf(stderr, "% 2d: %p %s+%u (%s)/n",
                                ++f,
                                ip,
                                symname,
                                (unsigned)(ip - dlinfo.dli_saddr),
                                dlinfo.dli_fname);

                if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
                        break;

                ip = bp[1];
                bp = (void**)bp[0];
        }
#else
        fprintf(stderr, "Stack trace (non-dedicated):/n");
        sz = backtrace(bt, 20);
        strings = backtrace_symbols(bt, sz);

        for(i = 0; i                 fprintf(stderr, "%s/n", strings[i]);
#endif
        fprintf(stderr, "End of stack trace/n");
        return;
}
int setup_sigsegv() {
        struct sigaction action;
        memset(&action, 0, sizeof(action));
        action.sa_sigaction = signal_segv;
        action.sa_flags = SA_SIGINFO;
        if(sigaction(SIGUSR1, &action, NULL)                 perror("sigaction");
                return 0;
        }

        return 1;
}

void func1()
{
        raise(SIGUSR1);
        return ;

}
void func2()
{
        raise(SIGUSR1);
        return ;

}

void entry()
{
        func1();
        func2();
        return;
}
int main()
{
        setup_sigsegv();
        entry();
}

gcc -o funstack -rdynamic -ldl funstack.c
初步看来还不错有空加到我原来俄内存检测程序中看看效果

本文转自
http://bbs.chinaunix.net/thread-950357-2-1.html

抱歉!评论已关闭.