ASAN 使用
- 安装asan库
一般gcc4.8以上带,但默认不会安装
yum install libasan*
- 编译选项
LDADD +=-L/usr/lib/gcc/aarch64-linux-gnu/7.3.0/ -lasan
LFLAGS = -g1 -fsanitize=address -fno-omit-frame-pointer -O1
- 运行
export ASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:detect_leaks=1:malloc_context_size=15:log_path=/userdata/logasan/
LD_PRELOAD=/usr/lib/gcc/aarch64-linux-gnu/7.3.0/libasan.so /var/eyou/queue/bin/smtpd
backtrace()的使用
在退出位置调用下面dump()
#ifdef __linux
#include <sys/syscall.h>
#endif
#include <execinfo.h> /* for backtrace() */
#define BACKTRACE_SIZE 1024
void dump(void)
{
int j, nptrs;
void *buffer[BACKTRACE_SIZE];
char **strings;
nptrs = backtrace(buffer, BACKTRACE_SIZE);
eyou_syslog("backtrace() returned %d addresses\n", nptrs);
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
eyou_syslog(" [%02d] %s\n", j, strings[j]);
if(strings != NULL)
{
printf("dump free strings err s\n");
free(strings);
strings = NULL;
}
}
- Linux例子:
#include <stdio.h>
#include <stdlib.h>
void access_invalid_memory() {
int* ptr = malloc(sizeof(int));
*ptr = 10;
free(ptr);
printf("The value is: %d\n", *ptr); // 这里访问已经释放的内存
}
int main() {
access_invalid_memory();
return 0;
}
编译:
gcc -g example.c -o example -fsanitize=address
运行:
./example
=================================================================
==5828== ERROR: AddressSanitizer: heap-use-after-free on address 0x60040000dff0 at pc 0x4008e7 bp 0x7fff352b37c0 sp 0x7fff352b37b0
READ of size 4 at 0x60040000dff0 thread T0
#0 0x4008e6 (/root/test/memory_check_tool/asan/example+0x4008e6)
#1 0x40090d (/root/test/memory_check_tool/asan/example+0x40090d)
#2 0x7fc641109554 (/usr/lib64/libc-2.17.so+0x22554)
#3 0x400788 (/root/test/memory_check_tool/asan/example+0x400788)
0x60040000dff0 is located 0 bytes inside of 4-byte region [0x60040000dff0,0x60040000dff4)
freed by thread T0 here:
#0 0x7fc6414caff9 (/usr/lib64/libasan.so.0.0.0+0x15ff9)
#1 0x4008af (/root/test/memory_check_tool/asan/example+0x4008af)
#2 0x40090d (/root/test/memory_check_tool/asan/example+0x40090d)
#3 0x7fc641109554 (/usr/lib64/libc-2.17.so+0x22554)
previously allocated by thread T0 here:
#0 0x7fc6414cb119 (/usr/lib64/libasan.so.0.0.0+0x16119)
#1 0x40085e (/root/test/memory_check_tool/asan/example+0x40085e)
#2 0x40090d (/root/test/memory_check_tool/asan/example+0x40090d)
#3 0x7fc641109554 (/usr/lib64/libc-2.17.so+0x22554)
Shadow bytes around the buggy address:
0x0c00ffff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c00ffff9bf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fd]fa
0x0c00ffff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c00ffff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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 righ 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
ASan internal: fe
==5828== ABORTING
valgrind memcheck
安装
yum install valgrind -y
说明:
-
概念:
Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。
Valgrind包括memcheck、Callgrind、Cachegrind、Helgrind、Massif等工具。
memcheck用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete 的调用都会被捕获。
-
命令行
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --undef-value-errors=no --log-file=log ./可执行程序名
–tool=memcheck:使用 memcheck 工具检测内存错误,包括使用未初始化的变量、读写越界等;
–leak-check=full:全面检测内存泄漏,不仅仅检测未释放的内存,还会检测处理时出现的一些问题;
–show-leak-kinds=all:显示所有的内存泄漏信息;
–undef-value-errors=no:不检查未定义的值错误;
–log-file=log:将日志信息输出到 log 文件中;
示例:
testValgrind.cpp
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void MyTest()
{
char* p = (char*)malloc(sizeof(char)*10);
delete[] p;
cout << "MyTest finished" << endl;
delete[] p;
}
int main()
{
MyTest();
return 0;
}
编译:
g++ -o testValgrind testValgrind.cpp
检查内存:
valgrind --leak-check=yes ./testValgrind
结果:
==12366== Memcheck, a memory error detector
==12366== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==12366== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==12366== Command: ./testValgrind
==12366==
==12366== Mismatched free() / delete / delete []
==12366== at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==12366== by 0x400898: MyTest() (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== by 0x4008D2: main (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== Address 0x5ab1c80 is 0 bytes inside a block of size 10 alloc'd
==12366== at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==12366== by 0x400881: MyTest() (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== by 0x4008D2: main (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366==
MyTest finished
==12366== Invalid free() / delete / delete[] / realloc()
==12366== at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==12366== by 0x4008C7: MyTest() (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== by 0x4008D2: main (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== Address 0x5ab1c80 is 0 bytes inside a block of size 10 free'd
==12366== at 0x4C2BB8F: operator delete[](void*) (vg_replace_malloc.c:651)
==12366== by 0x400898: MyTest() (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== by 0x4008D2: main (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== Block was alloc'd at
==12366== at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==12366== by 0x400881: MyTest() (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366== by 0x4008D2: main (in /root/test/memory_check_tool/memcheck/testValgrind)
==12366==
==12366==
==12366== HEAP SUMMARY:
==12366== in use at exit: 0 bytes in 0 blocks
==12366== total heap usage: 2 allocs, 3 frees, 72,714 bytes allocated
==12366==
==12366== All heap blocks were freed -- no leaks are possible
==12366==
==12366== For lists of detected and suppressed errors, rerun with: -s
==12366== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Dmalloc
参考:https://www.cnblogs.com/renhl/p/3302486.html
- 下载:
http://dmalloc.com/releases/
- 安装:
tar zxvf dmalloc-5.5.2.tgz
cd dmalloc-5.5.2
./configure --prefix=/usr
make
make install
- 使用:
设置环境变量:在~/.bashrc添加
function dmalloc { eval `command dmalloc -b $*`; }
然后重新登陆用户,或者执行:
source ~/.bashrc
- 示例代码:
//gcc -DDMALLOC -DDMALLOC_FUNC_CHECK -ldmalloc test.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef DMALLOC
#include <dmalloc.h>
#endif
int main(int argc, char **argv)
{
char *string;
string = (char*)malloc(sizeof(char));
string = (char*)malloc(sizeof(int*));
return 0;
}
- 编译:
gcc -DDMALLOC -DDMALLOC_FUNC_CHECK -ldmalloc test.c -L/root/test/memory_check_tool/Dmalloc/dmalloc-5.5.2/ -l dmalloc
dmalloc -l logfile -i 100 low
- 运行:./a.out
- 查看logfile
1711700382: 2: Dmalloc version '5.6.5' from 'http://dmalloc.com/'
1711700382: 2: flags = 0x4e48503, logfile 'logfile'
1711700382: 2: interval = 100, addr = 0x0, seen # = 0, limit = 0
1711700382: 2: starting time = 1711700382
1711700382: 2: process pid = 15807
1711700382: 2: Dumping Chunk Statistics:
1711700382: 2: basic-block 4096 bytes, alignment 8 bytes
1711700382: 2: heap address range: 0x7f5c7b993000 to 0x7f5c7b9a4000, 69632 bytes
1711700382: 2: user blocks: 2 blocks, 8153 bytes (14%)
1711700382: 2: admin blocks: 12 blocks, 49152 bytes (85%)
1711700382: 2: total blocks: 14 blocks, 57344 bytes
1711700382: 2: heap checked 1
1711700382: 2: alloc calls: malloc 2, calloc 0, realloc 0, free 0
1711700382: 2: alloc calls: recalloc 0, memalign 0, valloc 0
1711700382: 2: alloc calls: new 0, delete 0
1711700382: 2: current memory in use: 9 bytes (2 pnts)
1711700382: 2: total memory allocated: 9 bytes (2 pnts)
1711700382: 2: max in use at one time: 9 bytes (2 pnts)
1711700382: 2: max alloced with 1 call: 8 bytes
1711700382: 2: max unused memory space: 39 bytes (81%)
1711700382: 2: top 10 allocations:
1711700382: 2: total-size count in-use-size count source
1711700382: 2: 8 1 8 1 test.c:12
1711700382: 2: 1 1 1 1 test.c:11
1711700382: 2: 9 2 9 2 Total of 2
1711700382: 2: Dumping Not-Freed Pointers Changed Since Start:
1711700382: 2: not freed: '0x7f5c7b998fe8|s1' (8 bytes) from 'test.c:12'
1711700382: 2: not freed: '0x7f5c7b9a3ff8|s1' (1 bytes) from 'test.c:11'
1711700383: 2: total-size count source
1711700383: 2: 8 1 test.c:12
1711700383: 2: 1 1 test.c:11
1711700383: 2: 9 2 Total of 2
1711700383: 2: ending time = 1711700383, elapsed since start = 0:00:01
- Dmalloc version ‘5.6.5’ from ‘http://dmalloc.com/’:显示DMALLOC版本信息。
- flags = 0x4e48503, logfile ‘logfile’:显示一些标志和日志文件名。
- heap address range: 0x7f5c7b993000 to 0x7f5c7b9a4000, 69632 bytes:显示堆的地址范围和大小。
- user blocks: 2 blocks, 8153 bytes (14%):显示用户分配的内存块数量和大小。
- admin blocks: 12 blocks, 49152 bytes (85%):显示管理(内部)分配的内存块数量和大小。
- alloc calls: malloc 2, calloc 0, realloc 0, free 0:显示不同内存分配函数的调用次数。
- current memory in use: 9 bytes (2 pnts):当前使用的内存大小。
- max in use at one time: 9 bytes (2 pnts):最大同时使用的内存大小。
- top 10 allocations:显示前十个内存分配情况。
- Dumping Not-Freed Pointers Changed Since Start:显示从开始以来未释放的指针。
- ending time = 1711700383, elapsed since start = 0:00:01:显示结束时间和从开始到结束的时间。
Dmalloc的局限性:
-
Dmalloc只能检测堆上内存,对栈内存和静态内存无能为力。
-
dmalloc只用于利用malloc申请的内存,对使用sbrk()或mmap()分配的内存无能为力。
-
dmalloc不能用于检测读写没有申请的或者没有初始化的内存,也不能检测写只读内存。
cppcheck
- 下载:
Cppcheck - A tool for static C/C++ code analysis
- 安装:
tar -zxvf cppcheck-2.13.0.tar.gz
cd cppcheck-2.13.0
- 手动设置 FILESDIR 变量: 在执行 make 命令之前,先手动设置 FILESDIR 变量的值:
export FILESDIR=/usr/share/cppcheck
尝试:
yum install g++ make python
yum install python3
make MATCHCOMPILER=yes CFGDIR=/usr/share/cppcheck HAVE_RULES=yes
make install
make clean
- 编译安装:
make -j
make install
- 使用:
查看cppcheck版本:
cppcheck --version
启用所有检查规则,检查某个文件
cppcheck --enable=all --inconclusive testValgrind.cpp
检查当前路径下的代码,并输出到 txt 文件 – err.txt
cppcheck testValgrind.cpp --output-file=err.txt
输出 xml 格式的日志文件 – log.xml
cppcheck testValgrind.cpp --enable=all --output-file=log.xml --xml
检查某个路径,不输出过程日志
cppcheck --quiet ../memcheck/
Clang Static Analyzer
- 安装:
yum install clang
查看版本:
clang --version
clang version 3.4.2 (tags/RELEASE_34/dot2-final)
Target: x86_64-redhat-linux-gnu
Thread model: posix
查看clang位置:
which clang
/usr/bin/clang
- 使用:
例子:example.c
#include <stdlib.h>
int main() {
int *ptr;
if (rand() > 0) {
ptr = malloc(10 * sizeof(int));
}
*ptr = 5;
return 0;
}
在example.c目录:
命令:
/usr/bin/clang --analyze example.c
结果:
example.c:8:10: warning: Dereference of undefined pointer value
*ptr = 5;
example.c:9:5: warning: Potential leak of memory pointed to by 'ptr'
return 0;
^~~~~~~~
2 warnings generated.
生成的example.plist文件是Clang Static Analyzer的分析结果报告,以plist(Property List)格式保存。这个plist文件包含了代码的静态分析结果,其中记录了各种警告、错误和建议的修复方法。
在这个plist文件中,你可以找到以下信息:
警告信息:包括代码中可能存在的问题,例如空指针解引用、内存泄漏、潜在的越界访问等。
错误信息:代码中的严重问题,可能导致程序崩溃或安全漏洞。
修复建议:针对每个问题,Clang Static Analyzer会提供一些建议的修复方法,帮助开发者改进代码质量。
可以使用不同的工具或者脚本来解析example.plist文件,从中提取出有用的信息,帮助开发者定位和解决代码中的潜在问题。