zoukankan      html  css  js  c++  java
  • Windbg找出memory leak的一种笨办法

      以下内容是转自 http://www.cnblogs.com/fbird/p/5889596.html

      以前做项目碰到过一个问题,在客户的站点上面发现有严重的内存泄漏。幸运的是我们找到了重现的步骤,一轮下来大概有几十兆的泄漏,但是以下常规方法却没啥用。

    • 用windbg把heap上面的object全部dump下来,和上一轮操作作比较,并不能发现什么有用的东西。
    • 大对象heap上面也没啥有用的东西。
    • 像.net memory profiler这种比较智能的工具也用不上,因为一轮操作下来已经能使工具out of memory。

      项目有几百万行代码,但是我们认为可能发生大内存泄漏的就几个点。把那几个点的代码都找了一遍,没有任何结果。左寻右找,终于找到了一种比较笨但是却很管用的方法。

    1. 打开Windbg, attach进程。

    2. 加载symbol

    3. 打断点 (可以用.logopen c:memoryleak.txt把log记下来)

    bp kernel32!virtualalloc ".printf"#alloc memory# %lu  \n ",dwo(esp+8);!clrstack;g;"

    4. 输入g然后回车让进程继续跑。

    5. 将重现步骤跑一遍,然后去review日志。

      接下来的过程比较笨,Review日志的过程中找到比较可疑的申请大块内存的点,注释代码,编译Assembly替换,看内存泄漏还在不在。最终还是找到了那个泄漏的地方,一个remoting的proxy,出了作用域但是其指向的内存去没有被自动释放。

    解决这个问题的最关键的就是下面这条命令:
         bp kernel32!virtualalloc ".printf"#alloc memory# %lu  \n ",dwo(esp+8);!clrstack;g;"

      它的作用就是在kernel32的virtualalloc函数上面打断点,当该函数被执行到的时候,就把该函数申请的内存数量(在esp+8这个位置,dwo是把这个里面的值转成十进制),以及调用该函数的托管栈(clrstack)打印出来,然后让函数继续跑(g)。

      需要说明的是,这个命令仅对32位进程有效,因为根据32位cpu的calling convention,esp+4是第一个参数位置,esp+8是第二个,以此类推。64位的进程要去再查一下对应的calling convention看相关参数在哪个位置。

    LPVOID WINAPI VirtualAlloc(
      _In_opt_ LPVOID lpAddress,
      _In_     SIZE_T dwSize,
      _In_     DWORD  flAllocationType,
      _In_     DWORD  flProtect
    );
  • 相关阅读:
    FineReport——函数
    FineReport——插入行策略
    FineReport——JS二次开发(CSS改变控件样式)
    FineReport——JS二次开发(下拉框)
    汽车系统
    Ubuntu Software setup
    Win 10 乱码 & 字体横过去了
    U-boot 2016.11 代码结构 dra7xx
    samba Ubuntu 16.04
    ftp Ubuntu16.04
  • 原文地址:https://www.cnblogs.com/renyuan/p/6184546.html
Copyright © 2011-2022 走看看