程序发生异常时,将函数的调用栈打印出来,可以大大提高定位效率。
Linux中提供了三个函数用来获取调用栈:
1
2
3
4
5
6
7
8
|
/* 获取函数调用栈 */
int
backtrace
(
void
*
*
buffer
,
int
size
)
;
/* 将调用栈中的函数地址转化为函数名称 并返回一个字符串数组 */
char
*
*
backtrace_symbols
(
void
*
const
*
buffer
,
int
size
)
;
/* 将调用栈中的函数地址转化为函数名称 并将其定入到文件中 */
void
backtrace_symbols_fd
(
void
*
const
*
buffer
,
int
size
,
int
fd
)
;
|
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
/* 打印调用栈的最大深度 */
#define DUMP_STACK_DEPTH_MAX 16
/* 打印调用栈函数 */
void
dump_trace
(
)
{
void
*
stack_trace
[
DUMP_STACK_DEPTH_MAX
]
=
{
0
}
;
char
*
*
stack_strings
=
NULL
;
int
stack_depth
=
0
;
int
i
=
0
;
/* 获取栈中各层调用函数地址 */
stack_depth
=
backtrace
(
stack_trace
,
DUMP_STACK_DEPTH_MAX
)
;
/* 查找符号表将函数调用地址转换为函数名称 */
stack_strings
=
(
char
*
*
)
backtrace_symbols
(
stack_trace
,
stack_depth
)
;
if
(
NULL
==
stack_strings
)
{
printf
(
" Memory is not enough while dump Stack Trace! \r\n"
)
;
return
;
}
/* 打印调用栈 */
printf
(
" Stack Trace: \r\n"
)
;
for
(
i
=
0
;
i
<
stack_depth
;
++
i
)
{
printf
(
" [%d] %s \r\n"
,
i
,
stack_strings
[
i
]
)
;
}
/* 获取函数名称时申请的内存需要自行释放 */
free
(
stack_strings
)
;
stack_strings
=
NULL
;
return
;
}
/* 测试函数 2 */
void
test_meloner
(
)
{
dump_trace
(
)
;
return
;
}
/* 测试函数 1 */
void
test_hutaow
(
)
{
test_meloner
(
)
;
return
;
}
/* 主函数 */
int
main
(
int
argc
,
char
*
argv
[
]
)
{
test_hutaow
(
)
;
return
0
;
}
|
编译时需要加上-rdynamic
参数,以得到符号名称,像下面这样:
1
|
gcc
-
rdynamic
backtrace
.
c
-
o
backtrace
|
执行./backtrace
运行程序,输出如下: