admin管理员组文章数量:1537955
在日常开发中,遇到段错误是很常见的事,其中一种情况 Out of memory(OOM),内存泄露问题一般不好查找,但是可以借助工具来快速定位。
这里介绍的工具是valgrind,这个工具在buildroot有提供,如下图,选中,然后重新编译
valgrind 工具
memcheck :检测程序中的内存问题,如内存泄漏,越界,非法指针等
callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。
cachegrind:分析CPU的cache命中率,丢失率,用于进行代码优化。
helgrind:用于检测多线程程序中出现的竞争问题
Massif:堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理和栈的大小。
先上个测试案例 1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char *p = malloc(1024);
char *p1 = malloc(512);
char buf[3] = {0};
strcpy(buf,"1234");
printf("buf==%s\n",buf);
p = NULL;
while(1);
}
这个例子在给两个指针分配内存后,p直接指向了NULL,程序退出。
编译程序:
gcc 1.c -g -o 1,其中-g是为了保留符号表,可以定位到代码中具体某一行
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --undef-value-errors=no --log-file=1.log ./1
tool=memcheck 表示检测内存问题。
leak-check=full 表示完全检测内存泄漏
–log-file=log 表示信息会输入到log文件中(有时文件内容比较多,这样方便分析)
等程序退出或者通过kill 方式再查看log信息。
==17242== Memcheck, a memory error detector
==17242== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17242== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==17242== Command: ./1
==17242== Parent PID: 12570
==17242==
==17242==
==17242== Process terminating with default action of signal 2 (SIGINT)
==17242== at 0x4005CF: main (1.c:13)
==17242==
==17242== HEAP SUMMARY:
==17242== in use at exit: 1,536 bytes in 2 blocks
==17242== total heap usage: 3 allocs, 1 frees, 2,560 bytes allocated
==17242==
==17242== 512 bytes in 1 blocks are still reachable in loss record 1 of 2
==17242== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17242== by 0x400594: main (1.c:8)
==17242==
==17242== 1,024 bytes in 1 blocks are definitely lost in loss record 2 of 2
==17242== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17242== by 0x400586: main (1.c:7)
==17242==
==17242== LEAK SUMMARY:
==17242== definitely lost: 1,024 bytes in 1 blocks
==17242== indirectly lost: 0 bytes in 0 blocks
==17242== possibly lost: 0 bytes in 0 blocks
==17242== still reachable: 512 bytes in 1 blocks
==17242== suppressed: 0 bytes in 0 blocks
==17242==
==17242== For counts of detected and suppressed errors, rerun with: -v
==17242== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
其中最重要的是 HEAP SUMMARY: 表示你的程序内存泄漏的大小
如上面显示有1536 bytes,后面就是泄露的详细信息,并且都有定位到行号。
LEAK SUMMARY关键字。表示内存泄漏的类型:
definitely lost:确定的内存泄漏,已经不能访问这块内存
indirectly lost:指向该内存的指针都位于内存泄露处
possibly lost:可能的内存泄露,仍然存在某个指针能够访问某快内存,但该指针指向的已经不是 该内存首位置
still reachable:内存指针还在还有机会使用或者释放,指针指向的动态内存还没有被释放就退出了
通过ctrl+c退出了程序,512字节内存仍然由p1指向,但p指向NULL,所以p1部分为are still reachable,但p为are definitely lost。
valgrind还有更多强大的功能,具体可以查看 valgrind -h
关于内存还存在越界的问题。还是上面的案例,数组buf只有3个字节,但是strcpy的时候给了4个,造成越界损坏其它数据的可能性。
如何查找这种情况呢?
可以在编译的时候加上 -fsanitize=address 选项
如:gcc 1.c -fsanitize=address -g -o 1
然后运行./1 ,就会发现
=================================================================
==32083==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffd32182b33 at pc 0x7f55e23cc904 bp 0x7ffd32182af0 sp 0x7ffd32182298
WRITE of size 5 at 0x7ffd32182b33 thread T0
#0 0x7f55e23cc903 in __asan_memcpy (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x8c903)
#1 0x400993 in main /1.c:10
#2 0x7f55e1f9683f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
#3 0x400818 in _start (/RD/alan.wang/1+0x400818)Address 0x7ffd32182b33 is located in stack of thread T0 at offset 35 in frame
#0 0x4008f5 in main /RD/alan.wang/1.c:6This frame has 1 object(s):
[32, 35) 'buf' <== Memory access at offset 35 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 __asan_memcpy
Shadow bytes around the buggy address:
0x100026428510: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026428520: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026428530: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026428540: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026428550: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100026428560: 00 00 f1 f1 f1 f1[03]f4 f4 f4 f3 f3 f3 f3 00 00
0x100026428570: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026428580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100026428590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000264285a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000264285b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==32083==ABORTING
运行的时候发现越界,有地址被覆盖的提示,并且会终止程序。
版权声明:本文标题:Linux快速定位内存泄露和内存越界 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1725886493a1047065.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论