【调试】打印函数栈,以及由函数指针输出函数名的方法
2016-11-30 17:18
316 查看
Before All
以下皆在linux环境下。windows上用vs可随时查看函数栈。用户态
打印函数栈
使用backtrace()相关函数来达到输出函数栈的目的,man backtrace查看详细的参数,返回值等信息。以下测试例,编译时需加上-rdynamic选项:
#include <stdio.h> #include <stdlib.h> #include <execinfo.h> #define SIZE 100 void myfunc3(void) { int nptrs; void *buffer[100]; char **strings; nptrs = backtrace(buffer, SIZE); printf("backtrace() returned %d addresses\n", nptrs); /* 1 means standard output */ backtrace_symbols_fd(buffer, nptrs, 1); /* or use backtrace_symbols() */ /* strings = backtrace_symbols(buffer, nptrs); if (strings == NULL) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } for (j = 0; j < nptrs; j++) printf("%s\n", strings[j]); free(strings); // */ } static void /* "static" means don't export the symbol... */ myfunc2() { myfunc3(); } void myfunc() { myfunc2(); } int main() { myfunc(); return 0; }
简单说下这3个函数的用法:
int backtrace(void **buffer, int size);
backtrace()把函数栈中的函数地址写到buffer数组,buffer数组的成员即void *类型。size表示把栈顶size个函数地址搞出来,如果想把函数栈完全搞出来,确保buffer数组和size足够大。
char **backtrace_symbols(void *const *buffer, int size);
void backtrace_symbols_fd(void *const *buffer, int size, int fd);
backtrace_symbols()或者backtrace_symbols_fd()与上边的backtrace()配合使用,起一个翻译作用,即把函数地址翻译为函数名(还有函数的偏移和返回地址)。backtrace_symbols()把buffer数组中的size个元素翻译为函数名,把字符串数组保存在返回值char **中,自带了malloc功能,用完需把返回值free,见测试例。backtrace_symbols_fd()前两个参数和前者一样,但是把结果字符串数组输出到fd中,如fd=1,即输出到屏幕。
由函数指针得到函数名
根据以上可以看出,backtrace_symbols和backtrace_symbols_fd可以用来将函数指针转换为函数名,函数指针的讲解可以参考这里,以下是测试例:#include<stdio.h> #include<execinfo.h> void hello_world() { printf("hello world!\n"); } int main() { void *func = hello_world; //注意这里必须转化为一个void *指针 backtrace_symbols_fd(&func, 1, 1); return 0; }
这里就把函数指针func的函数名输出了出来。
内核态
打印函数栈
使用dump_stack()函数。直接在需要查看函数栈的位置加入这一句,然后dmesg中就可以看到函数栈了。由函数指针得到函数名
内核中可以直接使用printk的%pf,%pF选项,%pF选项多打印偏移地址。测试例:void testname() { return; } void test() { void (*funcptr) = testname; printk("%pf\n", funcptr); }
小结
以上就是在用户态,内核态输出函数栈,以及由函数指针输出函数名的方法,在调试的过程中有时能帮助加深对代码的理解。相关文章推荐
- 写了一个将VxWorks的shell打印输出到指定内存中的接口,可广泛用于CLI下的调试函数显示以及故障自动捕获等功能,稍作修改可以适合其它嵌入式OS
- 1.如何避免野指针2.获取字符串的两种方法。以及malloc,calloc,ralloc的使用注意点3.二维三维数组4.数组和函数的区别
- Log输出打印输出LOG所在的函数名以及行号
- c语言中printf函数打印char型变量0xFF,输出为0xFFFFFFFF的解决方法
- /* 用指向指针的指针的方法对n个整数排序并输出 。要求将排序单独写成一个函数。n个整数在主函数中输入,最后在主函数中输出*/
- GetLastError使用以及打印输出方法
- unity中调用dll(char*,以及带有函数指针的参数)方法总结
- Android下打印调试堆栈方法总结以及strace工具使用
- 函数调试用函数printk打印内核信息的方法
- pycharm输出中文出现乱码的几种解决方法以及读取时打印出现乱码的解决
- Linux 程序开发打印 Debug 信息的使用技巧--C语言中几种输出调试信息的方法
- Struts2框架调试时,控制台打印输出大量<mime-mapping>相关信息,解决方法
- 习题 8.21 用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。n个整数在主函数中输入,最后在主函数中输出。
- Struts2框架调试时,控制台打印输出大量<mime-mapping>相关信息,解决方法
- c和C++的调试打印输出方法
- (用指针方法处理)有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数。编写一个函数实现上述功能,在主函数中输入n个整数,并输出调整后的n个数
- 输入、输出函数说明以及精度说明符的使用方法
- Linux 程序开发打印 Debug 信息的使用技巧--C语言中几种输出调试信息的方法
- C应用程序增加调试便利的方法,程序运行过程中输出运行的源文件名称 函数名称和当前行号
- SQL Server中的几个方法和Transact SQL 常用语句以及函数