时间:2021-05-02
一、问题
有个打印log的函数,想知道该函数执行的时候,之前执行了哪些函数?
二、分析
在应用程序打印函数栈需要通过函数backtrace(),该函数对应头文件如下:
1、三个与打印调用栈相关的函数
打印函数栈需要使用到以下3个函数
函数功能:用于获取当前线程的调用堆栈。参数:buffer:它是一个指针数组,函数获取的当前线程的调用堆栈将会被存放在buffer中。在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈 框架有一个返回地址。size:用来指定buffer中可以保存多少个void*元素。返回值:实际获取的指针个数,最大不超过size大小。
char** backtrace_symbols (void *const *buffer, int size);
函数功能:将从backtrace函数获取的信息转化为一个字符串数组。参数:buffer:从backtrace函数获取的数组指针。size:是该数组中的元素个数(backtrace函数的返回值)。返回值:是一个指向字符串数组的指针,它的大小同buffer相同。每个字符串包含了一个相对于buffer中对应元素的 可打印信息。它包括函数名,函数的偏移地址,和实际的返回地址。
注:
功能:backtrace_symbols_fd与backtrace_symbols函数具有相同的功能,不同的是它不会给调用者返回字符串数组,而是将结果写入文件描述符为fd的文件中,每个函数对应一行.它不需要调用malloc函数,因此适用于有可能调用该函数会失败的情况。参数:fd:通常填写STDOUT_FILENO
2. 链接库
在编译的时候需要加上**-rdynamic**选项。
该选项让链接器将所有符号添加到动态符号表中,这样才能将函数地址翻译成函数名,否则打印的结果是不会打印函数名的。
另外,这个选项不会处理static函数,所以,static函数的符号无法得到。
3. 举例
编译运行gcc编译时加上-rdynamic参数,通知链接器支持函数名功能(不加-rdynamic参数则无函数名打印):
执行结果:
4. 补充 address2line
同一个函数可以在代码中多个地方调用,如果我们只是知道函数,要想知道在哪里调用了该函数,可以通过address2line命令来完成,我们用第2步中编译出来的test2来做实验(address2line的-f选项可以打出函数名, -C选项也可以demangle):
address2line
三、内核代码中如何打印函数栈?
在Linux内核中提供了一个可以打印出内核调用堆栈的函数 dump_stack()。
该函数在我们调试内核的过程中可以打印出函数调用关系,该函数可以帮助我们进行内核调试,以及让我们了解内核的调用关系。
1. 头文件
该函数头文件为:
使用方式:
直接在想要查看的函数中添加
2. 举例
测试代码如下:hello.c
Makefile
编译安装模块
【注意】 都在root权限下操作
结果
可以看到在函数ccc中使用dump_stack()打印出了ccc的函数调用栈。
在内核开发中,我们可以使用dump_stack()来打印相关信息,同时在内核源码学习中也可以用来了解函数调用关系。
原文地址:https://mp.weixin.qq.com/s/odyYVeDpO_1NcS8U_QE0AQ
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
C++内部函数和外部函数函数本质上是全局的,因为一个函数要被另外的函数调用,但是,也可以指定函数只能被本文件调用,而不能被其他文件调用。根据函数能否被其他源文件
前言在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对
Python偏函数是通过functools模块被用户调用。偏函数partial应用函数在执行时,要带上所有必要的参数进行调用。但是,有时参数可以在函数被调用之前
首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题
首先还是应该科普下函数参数传递机制,传值和传引用是什么意思?函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基