Windows 调查内存泄漏

Windows 调查内存泄漏,windows,debugging,memory-management,memory-leaks,windbg,Windows,Debugging,Memory Management,Memory Leaks,Windbg,我们的应用程序内存泄漏速度很慢,在分析泄漏原因时,我已经完成了以下步骤: 在GFlags中启用用户模式堆栈跟踪数据库 在Windbg中,键入以下命令:!heap-stat-h 1250000(其中1250000是存在泄漏的堆的地址) 在比较多个转储之后,我发现大小为0xC的内存块随着时间的推移而增加,可能是内存泄漏 键入以下命令:!堆-flt s c 给出这些分配的UserPtr,最后: 打字!某些地址上的heap-p-a address始终显示以下分配调用堆栈: 0:000>!堆-p-a105

我们的应用程序内存泄漏速度很慢,在分析泄漏原因时,我已经完成了以下步骤:

  • 在GFlags中启用用户模式堆栈跟踪数据库
  • 在Windbg中,键入以下命令:!heap-stat-h 1250000(其中1250000是存在泄漏的堆的地址) 在比较多个转储之后,我发现大小为0xC的内存块随着时间的推移而增加,可能是内存泄漏
  • 键入以下命令:!堆-flt s c 给出这些分配的UserPtr,最后:
  • 打字!某些地址上的heap-p-a address始终显示以下分配调用堆栈:
  • 0:000>!堆-p-a10576ef8

    address 10576ef8 found in
    _HEAP @ 1250000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        10576ed0 000a 0000  [03]   10576ef8    0000c - (busy)
        mscoreei!CLRRuntimeInfoImpl::`vftable'
        7c94b244 ntdll!RtlAllocateHeapSlowly+0x00000044
        7c919c0c ntdll!RtlAllocateHeap+0x00000e64
        603b14a4 mscoreei!UtilExecutionEngine::ClrHeapAlloc+0x00000014
        603b14cb mscoreei!ClrHeapAlloc+0x00000023
        603b14f7 mscoreei!ClrAllocInProcessHeapBootstrap+0x0000002e
        603b1614 mscoreei!operator new[]+0x0000002b
        603d402b +0x0000005f
        603d5142 mscoreei!GetThunkUseState+0x00000025
        603d6fe8 mscoreei!_CorDllMain+0x00000056
        79015012 mscoree!ShellShim__CorDllMain+0x000000ad
        7c90118a ntdll!LdrpCallInitRoutine+0x00000014
        7c919a6d ntdll!LdrpInitializeThread+0x000000c0
        7c9198e6 ntdll!_LdrpInitialize+0x00000219
        7c90e457 ntdll!KiUserApcDispatcher+0x00000007
    
    这看起来像线程初始化调用堆栈,但我需要知道更多。
    为了找出泄漏的确切原因,您建议下一步做什么。

    第一件事是,新的操作员是
    new[]
    操作员,因此是否有相应的
    delete[]
    调用而不是普通的
    delete
    调用

    如果您怀疑这段代码,我会在它周围放置一个测试线束,例如,将它放在一个循环中,并执行100或1000次,它是否仍然泄漏并按比例执行

    您还可以使用process explorer或以编程方式使用来测量内存增加

    另一个明显的问题是,当您注释掉这个函数调用时,会发生什么,内存泄漏会消失吗?如果可能的话,您可能需要对代码进行二进制切分,以便通过注释掉代码每次将可能的可疑代码减少一半(大致),但是,更改代码的行为可能会导致更多问题或相关代码路径问题,这可能会导致内存泄漏或奇怪的行为

    编辑 在托管环境中工作时,请忽略以下内容


    您也可以考虑使用<代码> STL< /COD>或更好地引用引用的指针或类似的数组结构来管理对象的生存期。

    < P>使用GFLAG时记录的堆栈是不使用.PDB的,通常是不正确的。 由于已将泄漏跟踪到给定堆上的特定大小,因此可以尝试 在RTLALLOCATHEAP中设置活动中断,并使用正确的符号检查windbg中的堆栈。我已经成功地使用了以下方法。您必须对其进行编辑以适合您的堆和大小

     $$ Display stack if heap handle eq 0x00310000 and size is  0x1303
     $$ ====================================================================
    bp ntdll!RtlAllocateHeap "j ((poi(@esp+4) = 0x00310000) & (poi(@esp+c) = 0x1303) )'k';'gc'" 
    

    也许你会得到另一个堆栈和其他罪犯的想法。

    虽然没有指定语言,但mscoreei的存在!*建议这是一种托管语言,因此可能不需要删除、使用STL、boost等。问题是此调用堆栈显示CLR代码,而不是我的代码,因此我不知道在哪里搜索。当我看到类似dllmain的调用时,它似乎正在加载某个dll,mscoreei是什么?我对.net一无所知。这是您的dll还是第三方,不是MS.net dll?MS dll泄漏内存的可能性很小,因此这可能与调用代码的错误使用有关。您可以在函数
    bp mscoreei上设置断点!GetThunkUseState
    调用此函数时,请检查调用堆栈,看看它是否提供了比.net framework中事后转储mscoreei更多的信息。因此,我发布的整个调用堆栈不是客户端代码的一部分,因此我无法设置断点。您仍然可以在mscoreei中设置断点,如果命中次数太多,则只能在命中代码时设置断点。