c中如何打印函數(shù)調(diào)用堆棧,? 如何在一個函數(shù)中打印出來調(diào)用它的上一級函數(shù)名稱,?
比如在做內(nèi)存泄漏檢測的時候,發(fā)現(xiàn)只打印分配內(nèi)存點的信息還不夠,因為有時候有多個流程同時調(diào)用一個地方分配內(nèi)存,,最好能是象gdb那樣打印出函數(shù)調(diào)用的堆棧來更方便一些,。
如果是c++還能想到用拋出異常來嘗試一下,c里面有什么好方法么,?
原帖由 feasword 于 2007-6-17 20:06 發(fā)表
如題
如何在一個函數(shù)中打印出來調(diào)用它的上一級函數(shù)名稱,?
比如在做內(nèi)存泄漏檢測的時候,發(fā)現(xiàn)只打印分配內(nèi)存點的信息還不夠,,因為有時候有多個流程同時調(diào)用一個地方分配內(nèi)存,,最好能是象gdb那樣打印出函數(shù)調(diào)用的 ...
何不直接參考 gdb 的源碼?
原帖由 feasword 于 2007-6-17 20:06 發(fā)表
如題
如何在一個函數(shù)中打印出來調(diào)用它的上一級函數(shù)名稱,?
比如在做內(nèi)存泄漏檢測的時候,,發(fā)現(xiàn)只打印分配內(nèi)存點的信息還不夠,因為有時候有多個流程同時調(diào)用一個地方分配內(nèi)存,,最好能是象gdb那樣打印出函數(shù)調(diào)用的 ... - func1(....)
- {
- .....
- #ifdef MYFEBUG
- func2(....,__func__);
- #endif
- ....
- }
- #ifdef MYFEBUG
- func2(....,const char* funcname)
- #else
- func2(...)
- #endif
- {
- #ifdef MYFEBUG
- printf("%s:%s\n",__func__,funcname);
- #endif
- ....
- }
可以參考strace,,我好像還用過一個什么trace。,。,。。的
這問題C版ms討論了很多次了,,info gcc
__builtin_return_address
__builtin_frame_address
還有一個相關(guān)的,, info libc
glibc中,
backtrace
backtrace_symbols
試驗了一下,,好像只能打印出地址,,但是有函數(shù)名更方便些
在11樓的提示下在網(wǎng)上找了篇文章,自己裁減了一下
- //funstack.c
- #define _GNU_SOURCE
- #include <memory.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <signal.h>
- #include <ucontext.h>
- #include <dlfcn.h>
- #include <execinfo.h>
- #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 < sz; ++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) < 0) {
- 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();
- }
復(fù)制代碼
gcc -o funstack -rdynamic -ldl funstack.c
初步看來還不錯有空加到我原來俄內(nèi)存檢測程序中看看效果
|