zoukankan      html  css  js  c++  java
  • 内存泄露bug指南(一)

    内存泄露bug指一个内存由操作系统或内部内存“池”分配,但是用完后从未收回。这实际上是资源回收的失职。有些人以为内存泄露只在支持内存分配并提供内存重分配方法的语言中出现。例如:C#和java不会导致这种错误,因为它们不支持内存分配,或者有一个垃圾收集机制,即在内存区长期不使用时自动释放。事实不只这么简单。资源泄露可以出现于任何语言,而且常常是因为编程错误而起。

    症状:其症状往往是系统变慢或者突然崩溃,以及其他奇怪的症状。最容易发现的是系统的内存(或资源)在一段时间内减少而且不恢复。可以使用很多管理工具和命令、脚本等观察程序是否有内存泄露。

    RSS: "Resident Set Size", 实际驻留"在内存中"的内存数. 不包括已经交换出去的代码. 举一个例子: 如果你有一个程序使用了100K内存, 操作系统交换出40K内存, 那么RSS为60K. RSS还包括了与其它进程共享的内存区域. 这些区域通常用于libc库等.

    程序内存的信息(/proc/self/smaps):

    VMSIZE:      15316 KB
    RSS:          2560 KB total
                  1152 KB shared
                   428 KB private clean
                   980 KB private dirty

    RSS(private dirty)最接近程序所使用的内存,特别是从heap分配的内存。

    这也是我们最关心地方: 进程实际占用的内存数.

    下面看一个C程序中常见的内存泄露错误(最简单的例子)。这种bug最讨厌,因为内存有时被收回,有时却没有。

    test_memleak.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    int fun(void)
    {
            return (rand()>>3)%2;
    }
    int main()
    {
        srand( (unsigned)time(NULL));
        int n=100;
        int *buffer=new int[n+1];
        memset(buffer,0,n+1);
        if (fun())//sim error in the processing piece
        {
            printf("An error occurred.Skipping final stage\n");
            return -1;
        }
        delete [] buffer;
        return 0;
    }
    

    正常情况下,这段代码工作正常。如果某个业务处理没有错误,内存就会正常的释放。但如果出现错误,则不能被释放,就出现了泄露。当然使用过C++的人会告诉你使用“智能指针”,它们可以自动地释放自己所指向的内存。如果指针式全局的,没办法智能靠编程人员自动动手完成了。

    作为测试人员通过哪些手段发现程序的内存泄露呢?查找内存泄露的工具至少二十种以上,以前用过DTrace,linux下改成systemtap,不过基本原理是一样的,感兴趣的请阅读我的其他文章,此工具使用起来还是比较麻烦。还有比较流行的工具Valgrind,大多数C程序员都接触过,个人感觉查找内存泄露过程中较大的影响应用的性能。看过google perftools工具箱中,提供Heap Checker堆内存泄漏检测工具,使用简单,并能够动态检测。

    HeapChecker包括normal在内总共有4种泄漏检查方式:minimal,忽略进入main函数之前的初始化过程;normal,报告所有的无法再引用的内存对象;strick,在normal的基础上增加一些额外的检查;draconian,在程序退出的时候存在未释放的内存的情况下报错。

    先在链接被检查程序的时候用-ltcmalloc选项连接GoolgePerftools的堆内存管理库tcmalloc(tcmalloc会替代C的堆内存管理库),然后每次用命令行“env HEAPCHECK=normal 可执行程序路径”来进行检查,其中检查形式normal可以替换成其他值,检查的结果会以屏幕报告的形式给出。

    g++ -O0 -g test_memleak.cpp -ltcmalloc -o test_memleak
    env HEAPCHECK=normal /root/src/test_memleak

     [root@s144 src]# env HEAPCHECK=normal /root/src/test_memleak
    WARNING: Perftools heap leak checker is active -- Performance may suffer
    No leaks found for check "_main_" (but no 100% guarantee that there aren't any): found 17 reachable heap objects of 710 bytes
    [root@s144 src]# env HEAPCHECK=normal /root/src/test_memleak
    WARNING: Perftools heap leak checker is active -- Performance may suffer
    No leaks found for check "_main_" (but no 100% guarantee that there aren't any): found 17 reachable heap objects of 710 bytes

  • 相关阅读:
    jQuery Colorpicker Spectrum api 中文 文档 属性 事件 方法
    java使用dbutils工具类实现小程序 管家婆记账软件
    java实现服务端开启多线程处理客户端的上传图片请求
    java 基于tcp客户端服务端发送接收数据
    java基于udp实现键盘录入聊天
    java实现udp发送端和接收端
    java通过读取本地文件获取反射方法参数,执行对象方法
    java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束
    Java反射获取类对象的三种方式
    java使用DBCP连接池创建工具类
  • 原文地址:https://www.cnblogs.com/jinyz/p/3066782.html
Copyright © 2011-2022 走看看