Linux下编程之内存检查

前言       

        我们在进行编程时,有时不免会无意中写出一些容易导致内存问题(可能一时表象上正常)的代码,导致的后果肯定是不好的,就像一颗颗“哑弹”,令人心慌。网上推荐的辅助工具很多,此篇文章只简单介绍其中的一种---经典的asan。

编译选项

        一般gcc和交叉编译工具链里面应该都集成了(如果没有,自行添加或换个工具,本文免读),只需在编译代码之前加上支持asan的编译选项即可。

        具体情况见下方代码块,根据自己的需求添加对应的编译选项。

Makefile
# 假设您的源文件是 main.c  
  
# 原来的编译命令可能是这样的  
main.o: main.c  
    gcc -c main.c  
  
# 修改后的编译命令,添加 -fsanitize=address 选项  
main.o: main.c  
    gcc -c -fsanitize=address main.c  
  
# 在链接时,您也需要添加相同的选项  
my_program: main.o  
    gcc -fsanitize=address main.o -o my_program

CMake
# CMakeLists.txt  
  
# 添加编译器选项  
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")  
  
# 或者使用 add_compile_options(对于较新的CMake版本)  
add_compile_options(-fsanitize=address)  
  
# 其余的CMake指令...

GCC命令行
gcc -fsanitize=address -o my_program my_program.c

Qt(.pro)
C++工程
QMAKE_CXXFLAGS += -fsanitize=address
C工程
QMAKE_CFLAGS += -fsanitize=address

示例

        下面只以gcc为例,演示asan的用法。

代码

        首先编写一份简单有内存泄漏的C代码(test.c),如下:

#include<stdio.h>

int main(int argc, char *argv[])
{
	char hello[6] = "hello";
	
	for(int i = 0; i <= 6; i++)
	{
	    printf("hello[%d] = %c\n", i, hello[i]);
	}

	return 0;
}

编译

gcc -fsanitize=address -o test_asan test.c

运行

root@ubuntu:/tmp# ./test_asan 
hello[0] = h
hello[1] = e
hello[2] = l
hello[3] = l
hello[4] = o
hello[5] = 
=================================================================
==11068== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffde1c9dd66 at pc 0x400919 bp 0x7ffde1c9dd10 sp 0x7ffde1c9dd08
READ of size 1 at 0x7ffde1c9dd66 thread T0
    #0 0x400918 (/tmp/test_asan+0x400918)
    #1 0x7f62939f6f44 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21f44)
    #2 0x4007a8 (/tmp/test_asan+0x4007a8)
Address 0x7ffde1c9dd66 is located at offset 38 in frame <main> of T0's stack:
  This frame has 1 object(s):
    [32, 38) 'hello'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
Shadow bytes around the buggy address:
  0x10003c38bb50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bb60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bb70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bb90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10003c38bba0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1[06]f4 f4 f4
  0x10003c38bbb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bbc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bbd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bbe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003c38bbf0: 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 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
==11068== ABORTING

从上面可以看出程序内存有溢出,溢出的地址也标明。

        如果将上述测试代码循环条件修改正确(i<6),重新编译再执行,结果如下,没有报错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值