zoukankan      html  css  js  c++  java
  • 【C++】C++代码动态检查

    代码动态检查方式

    • AddressSanitizer (ASan) 内存地址溢出检测器
    • LeakSanitizer (LSan) 内存泄露检测器
    • ThreadSanitizer (TSan) 线程互斥检测器
    • UndefinedBehaviorSanitizer (UBSsan) 没有定义的行为检测器
    • MemorySanitizer (MSan) 内存未初始化读取检测器

    一、内存地址溢出检测器

      1. 安装内存地址溢出检测库

    yum install libasan
    
    Installed:
      libasan.x86_64 0:4.8.5-36.el7_6.2

      2. 错误例子代码:

    #include <stdio.h>
    
    #define kBufSize 10
    
    char gArr[kBufSize];
    
    int main(int argc, char **argv) {
        char localArr[kBufSize];
        localArr[12] = 0x31;
        gArr[11] = 0x32;
        return gArr[11];
    }
    

      3. 编译代码(增加内存溢出检测)

    gcc -o a1 addresss.c -fsanitize=address -g
    

      4. 执行代码(检测内存溢出)

    [root@VM_93_229_centos test]# ./a1
    =================================================================
    ==6766== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc4c525bac at pc 0x4006c6 bp 0x7ffc4c525b60 sp 0x7ffc4c525b50
    WRITE of size 1 at 0x7ffc4c525bac thread T0
        #0 0x4006c5 (/home/dev/test/a1+0x4006c5)
        #1 0x7f5167e1c444 (/usr/lib64/libc-2.17.so+0x22444)
        #2 0x400588 (/home/dev/test/a1+0x400588)
    Address 0x7ffc4c525bac is located at offset 44 in frame <main> of T0's stack:
      This frame has 1 object(s):
        [32, 42) 'localArr'
    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:
      0x10000989cb20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cb30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cb40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cb50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cb60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    =>0x10000989cb70: f1 f1 f1 f1 00[02]f4 f4 f3 f3 f3 f3 00 00 00 00
      0x10000989cb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cb90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cbb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      0x10000989cbc0: 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
    ==6766== ABORTING
    

      5. 分析内存溢出信息

      错误信息显示变量 localArr 在内存指针 0x4006c6 处发生内存溢出错误。

      通过内存地址找到源码错误行。

    [root@VM_93_229_centos test]# addr2line -e ./a1 0x4006c6
    /home/dev/test/addresss.c:9
    [root@VM_93_229_centos test]# cat -n  addresss.c
         1	#include <stdio.h>
         2
         3	#define kBufSize 10
         4
         5	char gArr[kBufSize];
         6
         7	int main(int argc, char **argv) {
         8	    char localArr[kBufSize];
         9	    localArr[12] = 0x31;
        10	    gArr[11] = 0x32;
        11	    return gArr[11];
        12	}
    

      总结:修改localArr的内存溢出错误后,使用同样的方法监测gArr的内存溢出错误并修改。

    二、内存泄露检测器

      1. 安装内存泄露检测库

      

      2. 错误例子代码

    #include <stdio.h>
    
    int main(){
        int *ptr= new int(10);
        return 0;
    }
    

      

      3. 编译代码(增加内存泄露检测器)

    gcc leak.c -fsanitize=leak
    

      

      4. 执行代码(检测内存泄露)

      5. 分析

    三、线程安全检测器

      1. 安装线程安全检测库

    yum install libtsan
    
    Package libtsan-4.8.5-36.el7_6.2.x86_64 already installed and latest version
    

      

      2. 错误例子代码

    #include <pthread.h>
    #include <stdio.h>
    
    int global;
    
    void *Thread1(void *x) {
        global++;
        return NULL;
    }
    
    void *Thread2(void *x) {
        global--;
        return NULL;
    }
    
    int main() {
        pthread_t t[2];
        pthread_create(&t[0], NULL, Thread1, NULL);
        pthread_create(&t[1], NULL, Thread2, NULL);
        pthread_join(t[0], NULL);
        pthread_join(t[1], NULL);
    }
    

     

      3. 编译代码(增加线程安全检测器)

    gcc -o t tt.c -fsanitize=thread -fPIE -pie -g
    

      

      4. 执行代码(检测内存泄露)

    [root@centos test]# ./t
    ==================
    WARNING: ThreadSanitizer: data race (pid=9271)
      Read of size 4 at 0x7fc3c0c85068 by thread T1:
        #0 Thread1 /home/dev/test/tt.c:7 (exe+0x0000000009ed)
        #1 __tsan_write_range ??:0 (libtsan.so.0+0x00000001b1d9)
    
      Previous write of size 4 at 0x7fc3c0c85068 by thread T2:
        #0 Thread2 /home/dev/test/tt.c:12 (exe+0x000000000a68)
        #1 __tsan_write_range ??:0 (libtsan.so.0+0x00000001b1d9)
    
      Thread T1 (tid=9272, running) created by main thread at:
        #0 pthread_create ??:0 (libtsan.so.0+0x00000001f42b)
        #1 main /home/dev/test/tt.c:18 (exe+0x000000000ab5)
    
      Thread T2 (tid=9273, running) created by main thread at:
        #0 pthread_create ??:0 (libtsan.so.0+0x00000001f42b)
        #1 main /home/dev/test/tt.c:19 (exe+0x000000000ad6)
    
    SUMMARY: ThreadSanitizer: data race /home/dev/test/tt.c:7 Thread1
    ==================
    ThreadSanitizer: reported 1 warnings
    

      

      5. 错误分析

      错误显示文件tt.c的第7行和第12行有线程对data race操作(即:线程不安全操作)。

      #0 Thread1 /home/dev/test/tt.c:7 (exe+0x0000000009ed)
      #0 Thread2 /home/dev/test/tt.c:12 (exe+0x000000000a68)
    

      

    四、内存未初始化之前读取检测器

      1. 安装检测库

       

      2. 错误例子代码

    #include <iostream>
    
    int main(int argc, char** argv) {
        int* a = new int[10];
        a[5] = 0;
        if (a[argc])
            std::cout << a[3];
        return 0;
    }
    

      

      3. 编译代码(增加内存泄露检测器)

    gcc mm.c -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g
    

      

      4. 执行代码(检测内存泄露)

      5. 分析

     ----

    未完待续

  • 相关阅读:
    Linq to sql(八):继承与关系(二)
    Linq to sql(八):继承与关系(三)
    Linq to sql(八):继承与关系(五)
    div水平、垂直居中
    【转】C#读取QQ纯真IP数据库中的数据
    Flash被层遮挡的解决办法
    简易自定义分页
    网站来访者IP及地址记录
    安家第一篇
    天龙八部服务器端共享内存的设计
  • 原文地址:https://www.cnblogs.com/voipman/p/10974889.html
Copyright © 2011-2022 走看看