【问题标题】:How does String.Remove() operates regarding memory?String.Remove() 如何处理内存?
【发布时间】:2016-03-14 20:06:10
【问题描述】:

我想知道 .NET 的 string.Remove() 方法是如何处理内存的。

如果我有以下代码:

string sample = "abc";
sample = sample.Remove(0);

内存中实际会发生什么?

如果我理解正确,我们分配了一个由 3 个字符组成的字符串,然后我们在字符串的新副本上删除了所有这些字符,将副本分配给旧引用,然后覆盖它,然后是什么?这三个角色会发生什么?
如果我们不再指向它们,并且它们没有被释放(至少我不知道),它们将作为垃圾留在内存中。
但是,我确信 CLR 有某种方法可以检测到它并最终释放它们。

那么你们中的任何人都知道这里发生了什么吗?提前致谢!

【问题讨论】:

  • 是的,CLR 有一个垃圾收集器(即实际术语),它会定期运行并释放未使用的对象。
  • 听起来您实际上有一个问题,例如“如何安全地从内存中擦除字符串?”,并且您想知道string.Remove 是否是正确的方法。也许您应该询问前一个问题(作为一个新的 SO 问题),并提供有关您的特定场景的一些详细信息。
  • @Blorgbeard 从技术上讲,你是对的,我应该问像后者这样的问题,但我自己明白,如果这个问题的答案与 GC 相关,那么任何人都不安全意思是。

标签: c# string security memory


【解决方案1】:

首先Remove 将创建一个没有字符的新字符串(一个空字符串)。这将涉及分配一个 char 数组和一个 string 对象来包装它。然后你会将对该字符串的引用分配给你的局部变量。

由于字符串"abc" 是文字字符串,它仍将存在于实习池中,除非您禁用了编译时文字字符串的实习,因此它不会被垃圾回收。

总而言之,您创建了两个新对象并将变量sample 的引用从旧对象更改为新对象。

【讨论】:

  • 你的意思是分配一个char数组吗?
  • @Servy,如果您检查我链接到的源代码,Remove 确实会创建一个新字符串,但会为所需的字符数保留空间。本质上,不是空字符串。然后它将必要的字符复制到保留空间中。其他一切都是准确的。
  • @BerinLoritsch Remove 不会总是创建一个空字符串。但是,当您将 0 作为参数传递时,您将删除所有字符,因此剩下的是一个空字符串。您无需查看源代码即可知道这一点,只需查看该方法的文档即可。
  • @Servy 所以据我了解,在这种情况下,仅仅因为我分配了一个文字,它们将作为垃圾保留在内存中,但在任何其他情况下,这些字符将被垃圾收集,是吗?
  • @TimorGruber 在任何其他情况下,如果没有其他对该字符串的引用,那么它可能在 GC 发生时被收集 下一步运行。
【解决方案2】:

根据源码:http://referencesource.microsoft.com/#mscorlib/system/string.cs

  • Remove() 方法分配一个新的字符串对象并将结果返回给你
  • 在您的代码示例中,sample 变量被替换为不再具有第一个字符的新 string 对象
  • 当垃圾收集器触发时,孤立的字符串会被回收。

【讨论】:

  • 所以就安全性而言,这不是从内存中释放有关跟踪问题的字符串的正确方法,对吗?
  • @TimorGruber 我不确定,但如果你的目标是安全,你应该看看SecureString
  • 安全与此有什么关系?你有一个垃圾收集的语言。从内存中清除字符串的唯一方法是确保清除对该对象的所有引用并显式调用垃圾收集器。垃圾收集本质上是临时性的。
  • @BerinLoritsch 即使这样做也不能确保字符串中的数据不再在内存中。这就是垃圾收集语言的本质。
  • @TimorGruber 您是否希望恶意用户访问系统内存?如果是这样,那么您不能将该密码视为此类用户的安全密码,不。即使SecureString 也可能不会改变这一点。
猜你喜欢
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
  • 2017-06-25
  • 1970-01-01
  • 2015-01-26
  • 2020-05-24
  • 2019-10-08
  • 1970-01-01
相关资源
最近更新 更多