【问题标题】:memory leak when running the windbg script运行windbg脚本时内存泄漏
【发布时间】:2016-08-09 12:28:56
【问题描述】:
 .foreach (runtime {!da 00000086c74c3b70 })
{                                                
    .foreach(obj {!dumpobj  poi(poi(${runtime})+0x8)})

    {
         .if(0 == $sicmp("${obj}", "abcdxxxxxxx"))
         {

           .echo *****
           !dumpobj  poi(poi(${runtime})+0x8)
           !dumpobj  poi(${runtime})
           !dumpobj  poi(${runtime}+0x8)                                                     
           .echo *****
          }

    }   
}

我通过windbg运行上面的代码,windbg进程几乎消耗了我所有的PC内存(6G),即使上面的脚本运行完成也不会释放它。顺便说一句,!da 00000086c74c3b70 的结果大约是 8000 行 我的问题是如何释放内存或防止内存泄漏?

【问题讨论】:

  • .foreach ... !dumpobj 似乎没有意义。 `!dumpobj´ 作用于单个对象。你期望循环什么?垃圾场有多大? 6 GB 是否大致等于转储的大小?根据访问的内存,WinDbg 可能会将转储的这些部分读入内存,并且会像在任何其他程序中一样进行处理。
  • dump的大小在1G左右,数组的每个元素都是bucket,有如下布局,private struct bucket{ public object key; public object val; public int hash_coll;} ,而key的类型,也就是bucket的字段之一,是类,其中包含一个字符串字段。所以 poi(poi(${runtime})+0x8)} 的结果是 key 字段之一的字符串实例的地址,所以 !dumpobj poi(poi($ {runtime})+0x8) 包含字符串常量本身之外的许多字段,所以我使用 .foreach(obj {!dumpobj poi(poi(${runtime})+0x8)}) 进行过滤。
  • 顺便说一句,我参考下面的网址写windbg脚本debuggingtoolbox
  • @Jason WinDbg 泄漏是众所周知的。正如您所发现的,它在输出/解析大量数据的脚本中变得更加明显。据我所知,您对此无能为力。没有手动内存释放命令。不理想,但是当这种情况发生在我身上时,我通常会重新启动调试会话。您可以尝试向 Microsoft 报告它,但我不希望及时修复;我已经看到这个问题很多年了。
  • @dono 从 DrewBliss 到 Andyluhrs 观看 windbgfb@microsoft.com 的人们确实承认并回复,如果您报告重现问题的具体步骤的问题,模糊的不可重现的绝对陈述可能不会引起响应跨度>

标签: memory-leaks windbg


【解决方案1】:

让我们一步一步来 !da 的结果如下
你怎么能在不过滤的情况下做 .foreach

.foreach 将传递 Name:System.Int32MethodTable621ff680 ....
[0] ,,, [n] , [actual address] 在你的脚本中,难怪windbg
像地狱一样尝试从 Name , System.int32 字符串中读取废话,并试图将它们作为对象转储
我会说即使你有 60 GB 也不够,如果你这样做 .foreach 像这样需要一些时间来阅读文档

0:004> !da 016e1da4
Name:        System.Int32[]
MethodTable: 621ff680
EEClass:     61e3fd78
Size:        300(0x12c) bytes
Array:       Rank 1, Number of elements 72, Type Int32
Element Methodtable: 621ff6bc
[0] 016e1dac
[1] 016e1db0
[2] 016e1db4
[3] 016e1db8

您可能想在 16e1dac、db0、db4、db8 等上执行 .foreach?

如果是这样,您的第一行应该模仿这个即
而不是 dd 地方 l1 你应该使用你的 {? poi(${place}) } 随便
还要确保这里的每个取消引用实际上都可以被取消引用

0:004> .foreach /pS 16 /ps 1 (place { !da 016e1da4 } ) {dd place l1 }
016e1dac  00000003
016e1db0  00000007
016e1db4  0000000b
016e1db8  00000011
016e1dbc  00000017
016e1dc0  0000001d
016e1dc4  00000025

在这个例子中我不能取消引用任何东西 > poi(${place}) 因为它是一个 Int 数组

0:004> .foreach /pS 16 /ps 1 (place { !da -length 5 016e1da4 } ) {? poi(${place})  }
Evaluate expression: 3 = 00000003
Evaluate expression: 7 = 00000007
Evaluate expression: 11 = 0000000b
Evaluate expression: 17 = 00000011
Evaluate expression: 23 = 00000017

你不能随心所欲地期待理智的结果

【讨论】:

  • 您好 blabb,我会尝试您的解决方案,看看它是否有效并回复您,谢谢您的建议。
  • blabb ,我按照你的方式使用 .foreach /pS 16 /ps 1 ,是的,速度比以前更快了,但是内存泄漏持续存在并且不会自动释放。跨度>
猜你喜欢
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 2023-03-16
相关资源
最近更新 更多