c中如何打印函数调用堆栈? - C/C++ - ChinaUnix.net
2008-04-11 23:47
525 查看
导读:
试验了一下,好像只能打印出地址,但是有函数名更方便些
在11楼的提示下在网上找了篇文章,自己裁减了一下
[Copy to clipboard] [ - ]CODE:
//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 < 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();
}
gcc -o funstack -rdynamic -ldl funstack.c
初步看来还不错有空加到我原来俄内存检测程序中看看效果
本文转自
http://bbs.chinaunix.net/thread-950357-2-1.html
试验了一下,好像只能打印出地址,但是有函数名更方便些
在11楼的提示下在网上找了篇文章,自己裁减了一下
[Copy to clipboard] [ - ]CODE:
//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 < 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();
}
gcc -o funstack -rdynamic -ldl funstack.c
初步看来还不错有空加到我原来俄内存检测程序中看看效果
本文转自
http://bbs.chinaunix.net/thread-950357-2-1.html
相关文章推荐
- epoll的几个操作函数是线程安全吗? 表示怀疑~ - C/C++ - ChinaUnix.net -
- android如何在C++中打印调用堆栈
- c++里的system()函数调用系统命令如何获取打印信息
- 如何打印内核调用堆栈及函数名
- Asp.Net 如何调用js中的函数function ?
- c++ 如何把this指针传入成员函数 像全局函数一样调用成员函数
- C++中如何调用C里面的函数
- 如何通过C#调用OpenCV函数(自制OpenCV的c++ dll文件)
- PHP - 如何打印函数调用树
- Android下面打印进程函数调用堆栈(dump backtrace)的方法
- 在main函数退出后执行其他函数 http://blog.chinaunix.net/uid-22332450-id-1775058.html
- JNI中在被调用的C/C++函数中如何访问Java程序中的类,并编写应用实例
- C中如何调用C++函数的技巧(转)
- (转)如何在linux C/C++语言中调用 sqlite 的函数接口来实现对数据库的管理
- 如何在c里调用c++的类函数
- C中如何调用C++函数?
- C++.net如何跨线程调用windows控件
- asp.net Eval如何格式化日期、 调用后台函数的写法
- epoll是如何监控多个描述符及如何获得通知(1) http://blog.chinaunix.net/uid-23629988-id-3569332.html
- C++堆栈与函数调用