LINUX 多线程调试方法

LINUX环境下的 多线程调试方法与总结

作为开发者的天堂,Linux为程序员提供了极其便利的方法和技巧,同时随着程序规模的增加,线程之间的绕来绕去,程序调试变得极其不稳定,因此,如何判断程序的问题出在哪里变得尤其重要。本文总结前段时间,参与Linux开发调试遇到的一些技巧。

1 dmesg

在dmesg里我们可以查看到开机信息,printk产生的信息等。若研究内核代码,在代码中插入printk函数,然后通过dmesg观察是一个很好地方法。
默认

dmesg

LINUX 多线程调试方法_第1张图片
显示具体日期:

dmesg -T

LINUX 多线程调试方法_第2张图片
配合grep 方式过滤,可以看到有存在哪些问题。

2 coredump

当系统收到异常信号ARORT/SEGV时,系统会终止当前进程,并保留下来手机当时出现异常时的现场数据,类似于照相机按下快门的一瞬间,得到的照片即为我们的coredump。通常情况下coredmp包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理信息等。可以理解为把程序工作的当前状态存储成一个文件。许多程序和操作系统出错时会自动生成一个core文件。
可以利用coredump方式查看系统最后禅师异常的具体位置,一般来说,对于解决多线程和跨平台十分有效。

gcc -g src.cpp -o execute.file
ulimit -c unlimited
gdb execute.file core 
bt 查看调用栈信息

3 pwndbg

4 gdb+pstack

5 perf

1: 查看和分析指定程序的性能瓶颈

sudo perf top -p ${pid}

2: 检查每个线程的利用率:

perf stat --per-thread –p  ${pid}

ref:https://www.ibm.com/developerworks/cn/linux/l-cn-perf1/index.html
https://www.cnblogs.com/arnoldlu/p/6241297.html

6 iperf

iperf可以用来测量带宽
包括两个部分,分别为服务器以及客户端
1: 在服务器上,运行程序如下:

iperf -s -p 12345

2: 在客户端,运行:

iperf -c 12.12.10.12 -i 2 -P 10 -p 12345

3:客户端输出结果:

~$ iperf -c 12.12.10.12 -i 2 -P 10 -p 12345
------------------------------------------------------------
Client connecting to 12.12.10.12, TCP port 12345
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 12.12.10.11 port 50286 connected with 12.12.10.12 port 12345
[  6] local 12.12.10.11 port 50272 connected with 12.12.10.12 port 12345
[  5] local 12.12.10.11 port 50270 connected with 12.12.10.12 port 12345
[  7] local 12.12.10.11 port 50274 connected with 12.12.10.12 port 12345
[  4] local 12.12.10.11 port 50268 connected with 12.12.10.12 port 12345
[  8] local 12.12.10.11 port 50276 connected with 12.12.10.12 port 12345
[  9] local 12.12.10.11 port 50278 connected with 12.12.10.12 port 12345
[ 10] local 12.12.10.11 port 50280 connected with 12.12.10.12 port 12345
[ 11] local 12.12.10.11 port 50282 connected with 12.12.10.12 port 12345
[ 12] local 12.12.10.11 port 50284 connected with 12.12.10.12 port 12345

其中:

  • -i用于指定显示间隔,以秒为单位
  • -p用于指定连接的端口,默认为 5001
  • -P用于指定并发连接数,默认为1
    4: 服务端输出结果
$ iperf -s -p 12345
------------------------------------------------------------
Server listening on TCP port 12345
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[  4] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50268
[  5] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50272
[  6] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50270
[  7] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50274
[  8] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50276
[  9] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50278
[ 10] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50280
[ 11] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50284
[ 12] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50282
[ 13] local 12.12.10.12 port 12345 connected with 12.12.10.11 port 50286
[ ID] Interval       Transfer     Bandwidth
[  8]  0.0-10.0 sec  1.40 GBytes  1.21 Gbits/sec
[  9]  0.0-10.0 sec  1.41 GBytes  1.21 Gbits/sec
[  5]  0.0-10.0 sec   362 MBytes   303 Mbits/sec
[ 10]  0.0-10.0 sec  1.41 GBytes  1.21 Gbits/sec
[  4]  0.0-10.0 sec   358 MBytes   299 Mbits/sec
[  6]  0.0-10.0 sec   361 MBytes   302 Mbits/sec
[  7]  0.0-10.0 sec   361 MBytes   302 Mbits/sec
[ 13]  0.0-11.0 sec  1.78 GBytes  1.39 Gbits/sec
[ 11]  0.0-11.0 sec  1.77 GBytes  1.38 Gbits/sec
[ 12]  0.0-11.0 sec  1.77 GBytes  1.38 Gbits/sec
[SUM]  0.0-11.0 sec  11.0 GBytes  8.54 Gbits/sec

参考资料:
https://www.cnblogs.com/arnoldlu/p/6241297.html

7 strace 追踪程序运行

基本运行程序的命令包括:strace ./programs args

strace -tt -f ./Hello

运行结果:

10:13:27.919361 execve("./Hello", ["./Hello"], [/* 26 vars */]) = 0
10:13:27.919593 brk(NULL)               = 0x1de3000
10:13:27.919632 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
10:13:27.919673 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
10:13:27.919703 open("/home/newplan/project/makefile/tls/x86_64/libmytest.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.919738 stat("/home/newplan/project/makefile/tls/x86_64", 0x7ffd91a65910) = -1 ENOENT (No such file or directory)
10:13:27.919783 open("/home/newplan/project/makefile/tls/libmytest.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.919813 stat("/home/newplan/project/makefile/tls", 0x7ffd91a65910) = -1 ENOENT (No such file or directory)
10:13:27.919840 open("/home/newplan/project/makefile/x86_64/libmytest.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.919868 stat("/home/newplan/project/makefile/x86_64", 0x7ffd91a65910) = -1 ENOENT (No such file or directory)
10:13:27.919895 open("/home/newplan/project/makefile/libmytest.so", O_RDONLY|O_CLOEXEC) = 3
10:13:27.919925 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340\n\0\0\0\0\0\0"..., 832) = 832
10:13:27.919958 fstat(3, {st_mode=S_IFREG|0775, st_size=13288, ...}) = 0
10:13:27.919987 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7259274000
10:13:27.920019 mmap(NULL, 2105464, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7258e4d000
10:13:27.920046 mprotect(0x7f7258e4e000, 2097152, PROT_NONE) = 0
10:13:27.920073 mmap(0x7f725904e000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0x7f725904e000
10:13:27.920110 close(3)                = 0
10:13:27.920137 open("/home/newplan/project/makefile/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920168 open("/home/$USER/.openmpi/lib/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920194 stat("/home/$USER/.openmpi/lib/tls/x86_64", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920221 open("/home/$USER/.openmpi/lib/tls/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920249 stat("/home/$USER/.openmpi/lib/tls", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920275 open("/home/$USER/.openmpi/lib/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920303 stat("/home/$USER/.openmpi/lib/x86_64", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920330 open("/home/$USER/.openmpi/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920357 stat("/home/$USER/.openmpi/lib", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920384 open("/usr/local/cuda-10.1/lib64/tls/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920413 stat("/usr/local/cuda-10.1/lib64/tls/x86_64", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920439 open("/usr/local/cuda-10.1/lib64/tls/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920466 stat("/usr/local/cuda-10.1/lib64/tls", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920493 open("/usr/local/cuda-10.1/lib64/x86_64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920520 stat("/usr/local/cuda-10.1/lib64/x86_64", 0x7ffd91a658e0) = -1 ENOENT (No such file or directory)
10:13:27.920548 open("/usr/local/cuda-10.1/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.920575 stat("/usr/local/cuda-10.1/lib64", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
10:13:27.920605 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
10:13:27.920633 fstat(3, {st_mode=S_IFREG|0644, st_size=152376, ...}) = 0
10:13:27.920660 mmap(NULL, 152376, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f725924e000
10:13:27.920686 close(3)                = 0
10:13:27.920713 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
10:13:27.920744 open("/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
10:13:27.920773 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260`\0\0\0\0\0\0"..., 832) = 832
10:13:27.920800 fstat(3, {st_mode=S_IFREG|0755, st_size=138696, ...}) = 0
10:13:27.920826 mmap(NULL, 2212904, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7258c30000
10:13:27.920853 mprotect(0x7f7258c48000, 2093056, PROT_NONE) = 0
10:13:27.920881 mmap(0x7f7258e47000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x17000) = 0x7f7258e47000
10:13:27.920914 mmap(0x7f7258e49000, 13352, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7258e49000
10:13:27.920945 close(3)                = 0
10:13:27.920972 open("/home/newplan/project/makefile/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921001 open("/usr/local/cuda-10.1/lib64/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921030 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
10:13:27.921058 open("/usr/lib/x86_64-linux-gnu/libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
10:13:27.921086 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \235\10\0\0\0\0\0"..., 832) = 832
10:13:27.921114 fstat(3, {st_mode=S_IFREG|0644, st_size=1566440, ...}) = 0
10:13:27.921141 mmap(NULL, 3675136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f72588ae000
10:13:27.921169 mprotect(0x7f7258a20000, 2097152, PROT_NONE) = 0
10:13:27.921198 mmap(0x7f7258c20000, 49152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x172000) = 0x7f7258c20000
10:13:27.921229 mmap(0x7f7258c2c000, 13312, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7258c2c000
10:13:27.921261 close(3)                = 0
10:13:27.921292 open("/home/newplan/project/makefile/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921321 open("/usr/local/cuda-10.1/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921349 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
10:13:27.921377 open("/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
10:13:27.921405 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0V\0\0\0\0\0\0"..., 832) = 832
10:13:27.921433 fstat(3, {st_mode=S_IFREG|0644, st_size=1088952, ...}) = 0
10:13:27.921459 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f725924d000
10:13:27.921489 mmap(NULL, 3178744, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f72585a5000
10:13:27.921515 mprotect(0x7f72586ad000, 2093056, PROT_NONE) = 0
10:13:27.921542 mmap(0x7f72588ac000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x107000) = 0x7f72588ac000
10:13:27.921577 close(3)                = 0
10:13:27.921605 open("/home/newplan/project/makefile/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921634 open("/usr/local/cuda-10.1/lib64/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921662 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
10:13:27.921691 open("/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3
10:13:27.921719 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p*\0\0\0\0\0\0"..., 832) = 832
10:13:27.921747 fstat(3, {st_mode=S_IFREG|0644, st_size=89696, ...}) = 0
10:13:27.921773 mmap(NULL, 2185488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f725838f000
10:13:27.921801 mprotect(0x7f72583a5000, 2093056, PROT_NONE) = 0
10:13:27.921828 mmap(0x7f72585a4000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x7f72585a4000
10:13:27.921864 close(3)                = 0
10:13:27.921892 open("/home/newplan/project/makefile/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921920 open("/usr/local/cuda-10.1/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
10:13:27.921948 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
10:13:27.921977 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
10:13:27.922004 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
10:13:27.922030 fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0
10:13:27.922057 mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7257fc5000
10:13:27.922084 mprotect(0x7f7258185000, 2097152, PROT_NONE) = 0
10:13:27.922114 mmap(0x7f7258385000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f7258385000
10:13:27.922145 mmap(0x7f725838b000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f725838b000
10:13:27.922176 close(3)                = 0
10:13:27.922207 open("/home/newplan/project/makefile/libclasselib.so", O_RDONLY|O_CLOEXEC) = 3
10:13:27.922237 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\10\0\0\0\0\0\0"..., 832) = 832
10:13:27.922265 fstat(3, {st_mode=S_IFREG|0775, st_size=8728, ...}) = 0
10:13:27.922291 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f725924c000
10:13:27.922321 mmap(NULL, 2101320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7257dc3000
10:13:27.922346 mprotect(0x7f7257dc4000, 2093056, PROT_NONE) = 0
10:13:27.922373 mmap(0x7f7257fc3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x7f7257fc3000
10:13:27.922406 close(3)                = 0
10:13:27.922451 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f725924b000
10:13:27.922481 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7259249000
10:13:27.922511 arch_prctl(ARCH_SET_FS, 0x7f7259249740) = 0
10:13:27.922586 mprotect(0x7f7258385000, 16384, PROT_READ) = 0
10:13:27.922629 mprotect(0x7f72588ac000, 4096, PROT_READ) = 0
10:13:27.923159 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7259248000
10:13:27.923239 mprotect(0x7f7258c20000, 40960, PROT_READ) = 0
10:13:27.923269 mprotect(0x7f7257fc3000, 4096, PROT_READ) = 0
10:13:27.923301 mprotect(0x7f7258e47000, 4096, PROT_READ) = 0
10:13:27.923330 mprotect(0x7f725904e000, 4096, PROT_READ) = 0
10:13:27.923358 mprotect(0x601000, 4096, PROT_READ) = 0
10:13:27.923387 mprotect(0x7f7259275000, 4096, PROT_READ) = 0
10:13:27.923412 munmap(0x7f725924e000, 152376) = 0
10:13:27.923445 set_tid_address(0x7f7259249a10) = 10916
10:13:27.923468 set_robust_list(0x7f7259249a20, 24) = 0
10:13:27.923498 rt_sigaction(SIGRTMIN, {0x7f7258c35b50, [], SA_RESTORER|SA_SIGINFO, 0x7f7258c41390}, NULL, 8) = 0
10:13:27.923526 rt_sigaction(SIGRT_1, {0x7f7258c35be0, [], SA_RESTORER|SA_RESTART|SA_SIGINFO, 0x7f7258c41390}, NULL, 8) = 0
10:13:27.923554 rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
10:13:27.923584 getrlimit(RLIMIT_STACK, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
10:13:27.923712 brk(NULL)               = 0x1de3000
10:13:27.923743 brk(0x1e15000)          = 0x1e15000
10:13:27.923818 futex(0x7f7258c2d1ac, FUTEX_WAKE_PRIVATE, 2147483647) = 0
10:13:27.923885 futex(0x7f7258c2d1b8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
10:13:27.923941 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 10), ...}) = 0
10:13:27.923979 write(1, "Hello, world!\n", 14Hello, world!
) = 14
10:13:27.924014 write(1, "Constructing the object of class"..., 35Constructing the object of class A
) = 35
10:13:27.924043 write(1, "Constructing the object of class"..., 35Constructing the object of class B
) = 35
10:13:27.924073 write(1, "Constructing the object of class"..., 35Constructing the object of class D
) = 35
10:13:27.924101 write(1, "Testing the object of class A\n", 30Testing the object of class A
) = 30
10:13:27.924129 write(1, "Testing the object of class B\n", 30Testing the object of class B
) = 30
10:13:27.924158 write(1, "Constructing the object of class"..., 35Constructing the object of class E
) = 35
10:13:27.924186 write(1, "Testing the object of class E\n", 30Testing the object of class E
) = 30
10:13:27.924213 write(1, "Testing the object of class D\n", 30Testing the object of class D
) = 30
10:13:27.924241 write(1, "Destroying the object of class E"..., 33Destroying the object of class E
) = 33
10:13:27.924269 write(1, "Destroying the object of class D"..., 33Destroying the object of class D
) = 33
10:13:27.924296 write(1, "Destroying the object of class B"..., 33Destroying the object of class B
) = 33
10:13:27.924323 write(1, "Destroying the object of class A"..., 33Destroying the object of class A
) = 33
10:13:27.924365 exit_group(0)           = ?
10:13:27.924470 +++ exited with 0 +++

valigrid内存检查工具

valgrind [options] prog-and-args

[options]: 常用选项包括了适用于所有Valgrind工具,可以分为如下三类:

1: 工具选择

具体的格式为: --tool=运行 valgrind中名为name的工具。默认memcheck,这些工具包括:

  • memcheck: 这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。
  • callgrind:它主要用来检查程序中函数调用过程中出现的问题。
  • cachegrind:它主要用来检查程序中缓存使用出现的问题。
  • helgrind:它主要用来检查多线程程序中出现的竞争问题。
  • massif它主要用来检查程序中堆栈使用中出现的问题。
  • extension可以利用core提供的功能,自己编写特定的内存调试工具

2:一些其他命令

  • -h –help显示帮助信息。
  • -version显示valgrind内核的版本,每个工具都有各自的版本。
  • -q –quiet安静地运行,只打印错误信息。
  • -v –verbose更详细的信息, 增加错误数统计。
  • -trace-children=no|yes跟踪子线程? [no]
  • -track-fds=no|yes跟踪打开的文件描述?[no]
  • -time-stamp=no|yes增加时间戳到LOG信息? [no]
  • -log-fd=输出LOG到描述符文件 [2=stderr]
  • -log-file=将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID
  • -log-file-exactly=输出LOG信息到 file
  • -log-file-qualifier=取得环境变量的值来做为输出信息的文件名。 [none]
  • -log-socket=ipaddr:port输出LOG到socket ,ipaddr:port

3:LOG信息输出

  • -xml=yes将信息以xml格式输出,只有memcheck可用
  • -num-callers=show callers in stack traces [12]
  • -error-limit=no|yes如果太多错误,则停止显示新错误? [yes]
  • -error-exitcode=如果发现错误则返回错误代码 [0=disable]
  • -db-attach=no|yes当出现错误,valgrind会自动启动调试器gdb。[no]
  • -db-command=启动调试器的命令行选项[gdb -nw %f %p]

4:适用于Memcheck工具的相关选项

  • -leak-check=no|summary|full要求对leak给出详细信息? [summary]
  • -leak-resolution=low|med|highhow much bt merging in leak check [low]
  • -show-reachable=no|yesshow reachable blocks in leak check? [no]

5:一个例子

检测内存泄漏问题
使用命令:

valgrind --tool=memcheck --leak-check=full ./a.out
#include 
using namespace std;
int main()
{
    int *a = new int(2);
    //delete a;
    return 0;
}

检测结果如下:

$ valgrind --tool=memcheck --leak-check=full ./a.out
==702== Memcheck, a memory error detector
==702== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==702== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==702== Command: ./a.out
==702==
==702==
==702== HEAP SUMMARY:
==702==     in use at exit: 72,708 bytes in 2 blocks
==702==   total heap usage: 2 allocs, 0 frees, 72,708 bytes allocated
==702==
==702== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2
==702==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==702==    by 0x400717: main (in /home/newplan/project/gemm/a.out)
==702==
==702== LEAK SUMMARY:
==702==    definitely lost: 4 bytes in 1 blocks
==702==    indirectly lost: 0 bytes in 0 blocks
==702==      possibly lost: 0 bytes in 0 blocks
==702==    still reachable: 72,704 bytes in 1 blocks
==702==         suppressed: 0 bytes in 0 blocks
==702== Reachable blocks (those to which a pointer was found) are not shown.
==702== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==702==
==702== For counts of detected and suppressed errors, rerun with: -v
==702== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

参考资料

你可能感兴趣的:(系统调试)