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
    );
  • 相关阅读:
    Android生成自定义二维码
    Android快速实现二维码扫描--Zbar
    设计模式-桥接模式
    设计模式-组合模式
    设计模式-享元模式
    设计模式-适配器模式
    设计模式-装饰者模式
    设计模式-门面(外观)模式
    设计模式-原型模式
    设计模式-单例模式
  • 原文地址:https://www.cnblogs.com/renyuan/p/6184546.html
Copyright © 2011-2022 走看看