2017-07-25 51 views
0

众所周知,在某些情况下,当在C#中使用字符串时,CLR会将字符串interning作为优化来使用。是否有可能读取实习生池中的所有字符串?

所以我的问题是:

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

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

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

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

+5

_“不允许使用这些用例的原因是什么?”因为[每个功能都以-100分开始](https://blogs.msdn.microsoft.com/ericgu/2004/01/12/minus- 100分/),而团队则是在做一些实际有用的事情。 – stuartd

+8

“f这些都不可能,不允许这些用例的原因是什么?”这些不是用例 - 它们是API功能请求*,没有用例。一个用例可以解释为什么*你想要做这些事情。事后你说你不是在试图解决一个真正的问题,这表明你没有*用例。就我个人而言,我并不赞成混淆无用的功能。 –

+0

可能。通过* Microsoft.Diagnostics.Runtime *中的ClrMD API获取所有对象的列表,并使用* IsInterned *查找所有实例化的字符串。该API还可以提供您需要的其他统计信息。没有理由这样做,除非你正在编写一个调试器。 – IllidanS4

回答

3

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

但是,在调试程序时查找内存中的字符串是一种非常常见的用例,并且有工具可以执行此操作。

您将需要使用Windows SDK附带的工具WinDbg.exe。启动它并将其连接到你的程序执行完命令

.loadby sos clr 

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

!DumpHeap -strings 

并且您可以看到堆中的所有字符串对象。

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

1

可以分析串并重复这是有意义的实习生MemAnalyzer这是基于ClrMD

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 

这会给你一个指标,你有多少suplicate字符串有和他们的可能是有意义的实习生。要了解哪些对象引用的特定字符串,您可以添加

-showAddress

显示,这可能是值得每一个实习的strng第一个地址。然后你可以使用Windbg和!GCRoot地址来找出哪个对象持有这个字符串,这应该给你一个你需要添加String.Intern调用的类的想法。

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

相关问题