【问题标题】:How to prevent string being interned如何防止字符串被拦截
【发布时间】:2013-04-26 09:43:59
【问题描述】:

我的理解(可能是错误的)是,在 c# 中,当您创建一个字符串时,它会被实习到“实习池”中。这保留了对字符串的引用,以便多个相同的字符串可以共享操作内存。

但是,我正在处理很多很可能是唯一的字符串,一旦完成每个字符串,我需要将它们从操作内存中完全删除,我不确定如何删除缓存的引用,所以该垃圾收集器可以从内存中删除所有字符串数据。我怎样才能防止字符串被困在这个缓存中,或者我怎样才能清除它/或从中删除一个字符串,以便它肯定会从操作内存中删除?

【问题讨论】:

  • 除了默认行为之外,您想做其他事情的动机是什么?
  • 让 GC 完成它的工作。
  • 不是每个字符串都会被拘留,only literal strings
  • 好吧,但我猜如果引用保存在这个实习池中,GC不会只是从操作内存中删除字符串?或者它怎么知道哪个字符串可以删除,哪个不能删除?
  • 我的理解是,默认情况下,只有当它们是编译时常量或者你在它们上使用String.Intern 时,字符串才会被保留,正如broadcast.oreilly.com/2010/08/… 解释的那样。

标签: c# memory


【解决方案1】:

如果出于安全原因需要从内存中删除字符串,请使用SecureString

否则,如果任何地方都没有对字符串的引用,GC 无论如何都会清理它(它将不再被实习)所以你不必担心实习。

当然,首先只有字符串字面量会被实习(或者如果您调用 String.Intern(),如 Petr 和其他人在上面提到的)。

【讨论】:

  • @downvoter:你能解释一下为什么,只是为了帮助其他阅读这个答案的人吗?
  • SecureString 不是解决方案。这听起来“安全”,但如果我正确地阅读了他的问题,他不需要将它们从记忆中删除,因为他害怕黑客或其他东西。他只是想要恢复他的工作记忆。
  • @MartinMulder 这个问题并不完全清楚,因此在我的回答的第一行使用了“if”这个词。
  • 好吧,尽管这没有直接回答我的问题,但我接受了它,因为它不仅解释了我需要什么(我不需要关心运行时字符串,因为它们没有被实习,这是我不知道的),但它还引入了一种通用且简单的方法来创建一个永远不能被实习的字符串,并且尽可能短地保存在内存中(甚至加密),这是一件有趣的事情,这绝对是件好事知道。
【解决方案2】:

CompilationRelaxations 属性应用于整个程序集(看起来唯一可能的解决方案是禁止在程序集级别进行实习),如下所示:

[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)]

更多关于CompilationRelaxations的信息

更新:

文档说明该属性:

将程序集标记为不需要字符串文字实习

也就是说,它不会阻止编译器做字符串 实习,只是提示它不是必需的。这 这方面的文档有点稀疏,但这似乎也 成为this MSDN forum post中的结论。

来自该属性的this SO question

【讨论】:

  • 将程序集标记为不需要字符串文字实习与说应该关闭该功能不同social.msdn.microsoft.com/Forums/en-US/clr/thread/…
  • @TimSchmelter 使用相关 SO 问题的链接 + 解释更新了答案并提到了 MSDN 线程。谢谢
  • CompilationRelaxations 仅适用于代码中已有的常量字符串,不适用于运行时字符串。 Petr 正在谈论运行时字符串。
【解决方案3】:

你在说事情:

  • 您正在处理大量字符串,因此您在谈论运行时值。
  • 您希望在处理完字符串后从内存中删除它们。

默认情况下,运行时值不会被保留。当您从文件接收字符串或自己创建字符串时,它们都有一个单独的实例。您可以通过 String.Intern 实习他们。实习字符串需要更多时间,但消耗更少的内存。见:http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

如果没有引用运行时字符串,GC 会自动删除它们。实习生会有更多的参考资料,但在您的流程结束时,我假设所有参考资料都已删除。 interning-mechanism 不保留 HARD 引用,而是 WEAK 引用。 GC 会忽略弱引用,因此仍然可以删除字符串实例。见:http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

所以...总结一下。默认情况下,您的运行时字符串不会被实习。如果他们被拘留,他们仍然会在你的工作完成后被 GC 删除。

【讨论】:

    【解决方案4】:

    在尝试阻止实习之前,我建议使用String.IsInterned() 来确定您所关心的字符串是否真的被实习了。如果该函数返回 null,则您的字符串不会被保留。

    据我所知,在运行时动态生成的字符串根本不会被实习,因为不会带来性能优势。

    【讨论】:

      猜你喜欢
      • 2011-03-15
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 1970-01-01
      • 2015-06-04
      • 2016-01-06
      相关资源
      最近更新 更多