-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-f 跟踪由fork调用所产生的子进程.
-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号.
-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.
-h 输出简要的帮助信息.
-i 输出系统调用的入口指针.
-q 禁止输出关于脱离的消息.
-r 打印出相对时间关于,,每一个系统调用.
-t 在输出中的每一行前加上时间信息.
-tt 在输出中的每一行前加上时间信息,微秒级.
-ttt 微秒级输出,以秒了表示时间.
-T 显示每一调用所耗的时间.
-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.
-V 输出strace的版本信息.
-x 以十六进制形式输出非标准字符串
-xx 所有字符串以十六进制形式输出.
-a column
设置返回值的输出位置.默认 为40.
-e expr
指定一个表达式,用来控制如何跟踪.格式如下:
[qualifier=][!]value1[,value2]...
qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如:
-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.
注意有些shell使用!来执行历史记录里的命令,所以要使用\\.
-e trace=set
只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.
-e trace=file
只跟踪有关文件操作的系统调用.
-e trace=process
只跟踪有关进程控制的系统调用.
-e trace=network
跟踪与网络有关的所有系统调用.
-e strace=signal
跟踪所有与系统信号有关的 系统调用
-e trace=ipc
跟踪所有与进程通讯有关的系统调用
-e abbrev=set
设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all.
-e raw=set
将指 定的系统调用的参数以十六进制显示.
-e signal=set
指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号.
-e read=set
输出从指定文件中读出 的数据.例如:
-e read=3,5
-e write=set
输出写入到指定文件中的数据.
-o filename
将strace的输出写入文件filename
-p pid
跟踪指定的进程pid.
-s strsize
指定输出的字符串的最大长度.默认为32.文件名一直全部输出.
-u username
以username 的UID和GID执行被跟踪的命令
[root@v68869 sbin]# strace ./nginx 2>&1 | grep nginx.conf
open("/opt/nginx//conf/nginx.conf", O_RDONLY) = 4
[root@v68869 conf]# strace -e open cat nginx.conf
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("nginx.conf", O_RDONLY) = 3
[root@v68869 conf]# strace -p 23259
strace: Process 23259 attached
epoll_wait(8,
[{EPOLLIN, {u32=2768318480, u64=139739529293840}}], 512, -1) = 1
accept4(6, {sa_family=AF_INET, sin_port=htons(35326), sin_addr=inet_addr("218.98.33.164")}, [16], SOCK_NONBLOCK) = 3
epoll_ctl(8, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLET, {u32=2768318848, u64=139739529294208}}) = 0
epoll_wait(8, [{EPOLLIN, {u32=2768318848, u64=139739529294208}}], 512, 60000) = 1
recvfrom(3, "CONNECT init.itunes.apple.com:44"..., 1024, 0, NULL, NULL) = 218
writev(3, [{"\r\n400 Bad Req"..., 120}, {"
nginx/1.0.14 \r\n400 Bad Req"..., 120}, {"
nginx/1.0.14
[root@v68869 conf]# strace -c ls
fastcgi.conf fastcgi_params.default mime.types nginx.conf.default uwsgi_params
fastcgi.conf.default koi-utf mime.types.default scgi_params uwsgi_params.default
fastcgi_params koi-win nginx.conf scgi_params.default win-utf
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
25.25 0.001423 51 28 mmap
14.21 0.000801 45 18 mprotect
13.13 0.000740 67 11 open
9.44 0.000532 53 10 read
7.40 0.000417 30 14 close
6.53 0.000368 31 12 fstat
4.56 0.000257 129 2 2 statfs
3.55 0.000200 100 2 getdents
2.41 0.000136 45 3 munmap
2.15 0.000121 61 2 ioctl
1.85 0.000104 35 3 write
1.61 0.000091 30 3 brk
1.17 0.000066 33 2 1 access
1.14 0.000064 32 2 rt_sigaction
0.98 0.000055 55 1 openat
0.98 0.000055 55 1 set_robust_list
0.91 0.000051 51 1 execve
0.83 0.000047 47 1 getrlimit
0.76 0.000043 43 1 set_tid_address
0.71 0.000040 40 1 rt_sigprocmask
0.43 0.000024 24 1 1 stat
0.00 0.000000 0 1 arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00 0.005635 120 4 total
[root@v68869 conf]# strace -c -p 23259
strace: Process 23259 attached
^Cstrace: Process 23259 detached
[root@v68869 conf]# strace -c -p 23259
strace: Process 23259 attached
^Cstrace: Process 23259 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
29.12 0.000316 158 2 writev
19.72 0.000214 43 5 epoll_wait
18.53 0.000201 40 5 2 recvfrom
15.39 0.000167 84 2 shutdown
8.76 0.000095 48 2 epoll_ctl
8.48 0.000092 46 2 accept4
0.00 0.000000 0 1 write
0.00 0.000000 0 1 close
------ ----------- ----------- --------- --------- ----------------
100.00 0.001085 20 2 total
centos系统: yum install glibc-utils
#include
int main()
{
setenv("MALLOC_TRACE", "mtrace.log", "1");
mtrace();
int *p = (int *)malloc(2 * sizeof(int));
return 0;
}
mtrace
()开启内存使用记录,muntrace()
用于取消内存使用记录。内存使用情况记录到一个文件,值由环境变量:MALLOC_TRACE
决定。
编译源文件:gcc -g -DDEBUG testmtrace.c
执行:./a.out 产生mtrace.log
分析结果: mtrace ./a.out mtrace.log
[root@v68869 ~]# mtrace ./a.out mtrace.log
- 0x0000000001d04010 Free 3 was never alloc'd 0x7fcd53db596a
- 0x0000000001d040f0 Free 4 was never alloc'd 0x7fcd53e771fd
- 0x0000000001d04110 Free 5 was never alloc'd 0x7fcd53eeb9dc
Memory not freed:
-----------------
Address Size Caller
0x0000000001d04590 0x8 at /root/testmtrace.c:19
mtrace
采用 malloc_hook
+ return_addr
这两个机制来实现的
mtrace
会记录所有的分配、释放,包括所有的模块、线程。内存使用记录必将很多,所以官方推荐使用 SIGUSR1
或SIGUSR2
来进行开启和关闭内存记录功能。mtrace
记录和分析结果可以看到,内存记录日志只记录到 malloc
层面。而实际项目开发时,很多接口都是封装多层才会实际调用到 malloc
,对于上面几层的地址,mtrace
没有记录。而上面几层的调用关系才是追踪内存泄漏问题的关键所在。所以在实际开发的项目中,使用 mtrace
不是一个特别好的方法。这里推荐使用 valgrind
工具进行跑流程的方式追踪内存泄漏。如果想要自己记录内存使用情况,可以考虑以下两种方式:
ltrace 在某些方面和是trace功能类似
语法:ltrace [option ...] [command [arg ...]]
Usage: ltrace [option ...] [command [arg ...]]
Trace library calls of a given program.
-a, --align=COLUMN align return values in a secific column.
-c count time and calls, and report a summary on exit.
-C, --demangle decode low-level symbol names into user-level names.
-d, --debug print debugging info.
--dl show calls to symbols in dlopened libraries.
-e expr modify which events to trace.
-f follow forks.
-h, --help display this help and exit.
-i print instruction pointer at time of library call.
-l, --library=FILE print library calls from this library only.
-L do NOT display library calls.
-n, --indent=NR indent output by NR spaces for each call level nesting.
-o, --output=FILE write the trace output to that file.
-p PID attach to the process with the process ID pid.
-r print relative timestamps.
-s STRLEN specify the maximum string size to print.
-S display system calls.
-t, -tt, -ttt print absolute timestamps.
-T show the time spent inside each call.
-u USERNAME run command with the userid, groupid of username.
-V, --version output version information and exit.
-x NAME treat the global NAME like a library subroutine.
[root@bogon bin]# ltrace ./cli
(0, 0, 0x1321000, -1, 0x1f25bc2) = 0x3c9ba22160
__libc_start_main(0x462ba0, 1, 0x7fff89be1e08, 0x4c6450, 0x4c6440
pthread_spin_init(0x7bf600, 0, 0x7fff89be1e18, 8, 0x3c9bf8fba0) = 0
__cxa_atexit(0x4afff0, 0, 0x4c6548, 8, 0x3c9bf8fba0) = 0
__cxa_atexit(0x4a7550, 0, 0x4c6548, 9, 0x3c9bf8fba0) = 0
__cxa_atexit(0x4a7520, 0, 0x4c6548, 10, 0x3c9bf8fba0) = 0
pthread_spin_init(0x7c17e0, 0, 0, 11, 0x3c9bf8fba0) = 0
__cxa_atexit(0x4a2c80, 0, 0x4c6548, 11, 0x3c9bf8fba0) = 0
pthread_spin_init(0x7c18a4, 0, 0, 12, 0x3c9bf8fba0) = 0
__cxa_atexit(0x4a2c70, 0, 0x4c6548, 12, 0x3c9bf8fba0) = 0
strlen("*") = 1
memcpy(0x7c1660, "*", 1) = 0x7c1660
__cxa_atexit(0x481290, 0, 0x4c6548, 42, 0x596b7c) = 0
malloc(72) = 0x1bd9c40
pthread_mutex_lock(0x7bf540, 0x3c9bf8ef60, 0x1bd9c40, 81, 0x3c9bf8e188) = 0
pthread_mutex_unlock(0x7bf540, 0, 0x1bd9c40, 81, 0x7bf540) = 0
pthread_mutex_lock(0x7bf540, 0, 0x7bf540, 0, 0x7bf540) = 0
pthread_mutex_unlock(0x7bf540, 0, 0x7bf540, 0, 0x7bf540) = 0
pthread_spin_init(0x7c1788, 0, 0x7bf540, 0, 0x7bf540) = 0
pthread_mutex_lock(0x7bf540, 0, 0x7bf540, 0, 0x7bf540) = 0
pthread_cond_broadcast(0x7d1920, 0, 0x7bf540, 0, 0x7bf540) = 0
pthread_mutex_unlock(0x7bf540, 1, 0x7bf540, 0, 0x7bf540) = 0
__cxa_atexit(0x47fab0, 0, 0x4c6548, 0, 0x7bf540) = 0
pthread_spin_lock(0x7c1788, 13, 0, 15, 0x3c9bf8fba0) = 0
pthread_spin_unlock(0x7c1788, 13, 0, 15, 0x3c9bf8fba0) = 0
pthread_spin_init(0x7c16e8, 0, 0, 15, 0x3c9bf8fba0) = 0
strlen("C") = 1
memcpy(0x7c16f0, "C", 1) = 0x7c16f0
malloc(216) = 0x1bd9c90