是否可以读取实习池中的所有字符串?

时间:2017-07-25 20:10:14

标签: c# .net string clr

众所周知,在某些情况下,在C#中使用字符串时,CLR会将字符串实际作为优化。

所以我的问题是:

  • 可以读取当前实习池中的所有字符串吗?
  • 有没有办法获取每个实习字符串的引用计数?
  • 是否可以从单独的处理空间读取实习池?
  • 如果这些都不可能,那么不允许这些用例的原因是什么?

在某些情况下监视内存使用情况时,我可以看到这有点用处。在处理敏感信息时它也可能很有用(尽管我认为SecureString在许多情况下更为可取)。

据我所知,与字符串实习相关的唯一公共方法是String.Intern(string)String.IsInterned(string)

我是出于好奇而不是试图解决一个真正的问题。我意识到,根据字符串实习池做任何逻辑都是个坏主意。

2 个答案:

答案 0 :(得分:3)

通过代码查找实习字符串没有用例,所以它的功能没有添加到语言中。

然而,在调试程序时查找内存中的字符串是一个非常常见的用例,并且有工具可以做到这一点。

您需要使用Windows SDK附带的工具WinDbg.exe。启动它并将其附加到您的程序后,您可以执行命令

.loadby sos clr

这将加载调试.NET应用程序的扩展。完成后,您可以执行命令

!DumpHeap -strings

你可以看到堆中的所有字符串对象。

至于告诉您正在查看的列表中的对象是否被实习,我不完全确定如何。希望如果你问一个关于WinDbg的新问题,以及如何判断一个字符串是否被实习,或者某人可以回答。

答案 1 :(得分:1)

您可以使用基于 ClrMD MemAnalyzer 分析对实习生有意义的字符串和副本。

https://github.com/Alois-xx/MemAnalyzer

C>MemAnalyzer.exe -dstrings -f 50KStringsx64.dmp

    Strings(Count)  Waste(Bytes)    String
    500             20,958          String 0
    500             20,958          String 1
    500             20,958          String 2
    500             20,958          String 3
    500             20,958          String 4
    500             20,958          String 5

Summary
==========================================
Strings                       61,330 count
Allocated Size             2,529,742 bytes
Waste Duplicate Strings    2,515,898 bytes

这将为您提供一个指标,表明您拥有多少个字符串,以及哪些字符串可能对实习生有意义。要找出哪个对象引用了您可以添加的特定字符串

  

-showAddress

显示可能值得实习的每个strng的第一个地址。然后你可以使用Windbg和!GCRoot地址找出哪个对象包含这个字符串,它可以让你知道你需要在哪个类中添加String.Intern调用。

请注意,.NET String.Intern池永远不会释放引用。如果您正在处理具有不同内容的大型数据集,则应使用自己的字典池,以便在卸载当前数据集并加载下一个数据集时释放所有实体字符串。