C# 如何防止字符串被拘留

C# 如何防止字符串被拘留,c#,memory,C#,Memory,我的理解(这可能是错误的)是,在c#中,当你创建一个字符串时,它会被插入“实习生池”。它保留对字符串的引用,以便多个相同的字符串可以共享操作内存 然而,我正在处理很多很可能是唯一的字符串,一旦我处理完它们,我需要将它们从操作内存中完全删除,我不确定如何删除缓存引用,以便垃圾收集器可以从内存中删除所有字符串数据。如何防止字符串被缓存在缓存中,或者如何清除它/或从缓存中删除字符串,以便从操作内存中删除它?如果出于安全原因需要从内存中删除字符串,请使用 否则,如果任何地方都没有对该字符串的引用,GC将

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


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

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

否则,如果任何地方都没有对该字符串的引用,GC将无论如何清理它(它将不再被拘留),因此您不需要担心拘留问题


当然,首先只对字符串文本进行内部存储(或者如果您调用了上面Petr和其他人提到的string.Intern()。

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

[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)]
更多有关

更新:

文档说明属性:

将程序集标记为不需要字符串文字插入的

换句话说,它不会阻止编译器执行字符串 实习,只是暗示这不是必需的。这个 这方面的文档有点少,但这似乎也是一个问题 作为中的结论


从该属性开始

在尝试阻止插入之前,我建议使用该属性来确定您所关心的字符串是否实际被插入。如果该函数返回null,则字符串不会被插入


据我所知,在运行时动态生成的字符串根本不会被占用,因为这对性能没有好处。

你是在说:

  • 您正在处理大量字符串,因此您谈论的是运行时值
  • 您希望在处理完字符串后将其从内存中删除
默认情况下,运行时值不会被占用。当您从文件接收字符串或自己创建字符串时,它们都有一个单独的实例。你可以通过String.Intern对他们进行实习。插入字符串需要更多的时间,但占用的内存更少。见:

如果没有对运行时字符串的引用,则GC会自动删除这些字符串。实习医生会有更多的推荐信,但在你的过程结束时,我假设所有推荐信都会被删除。实习机制不是硬参考,而是弱参考。GC忽略弱引用,因此仍然可以删除字符串实例。见:


所以。。。总而言之。默认情况下,您的运行时字符串不会被占用。如果他们会被拘留,在你的工作完成后,他们仍然会被GC删除。

除了默认行为之外,你想做其他事情的动机是什么?让GC去做它的工作吧。不是每个字符串都会被拘留。好吧,但我想如果引用保留在这个实习池中,GC不会仅仅从操作内存中删除字符串?或者它如何知道哪些字符串可以删除,哪些不能删除?我的理解是,默认情况下,只有当字符串是编译时常量,或者如果您对其使用
string.Intern
,正如所解释的那样。@downvoter:您能解释一下原因吗,只是为了帮助其他阅读此答案的人?SecureString不是一个解决方案。这听起来“安全”,但如果我读对了他的问题,他不需要从内存中删除它们,因为他受到黑客或其他东西的袭击。他只是想找回自己的工作记忆。@MartinMulder这个问题并不完全清楚,因此在我回答的第一行中使用了“如果”这个词。好吧,尽管这不是直接回答我的问题,但我接受了它,因为它不只是解释我需要什么(我不需要关心运行时字符串,因为它们不是临时存储的,这是我不知道的),但它还引入了一种通用而简单的方法来创建一个永远不能临时存储的字符串,并尽可能短地保存在内存中(甚至加密),这是一件有趣的事情,知道它肯定很好。将程序集标记为不需要字符串文字实习,这与说应该关闭该功能不同@TimSchmelter updated answer,带有相关SO问题和提到的MSDN线程的链接+解释。Thanks编译松弛仅适用于常量st代码中已经有了响铃,而不是运行时字符串。Petr正在谈论运行时字符串。