字符串和垃圾收集

我听过有关这个主题的相互矛盾的故事,我正在寻找一点清晰。

如何立即处理一个string对象,或者至少清除它的痕迹?

那要看。 默认情况下,文字字符串是固定的,因此即使您的应用程序不再引用它,也不会收集它,因为内部实习结构会引用它。 其他字符串就像任何其他托管对象一样。 一旦它们不再被您的应用程序引用,它们就有资格进行垃圾收集。

更多关于这个问题的实习: Java和.NET字符串文字在哪里?

如果需要保护字符串并且能够在需要时进行处理,请使用System.Security.SecureString类。

使用.NET 2.0的SecureString类保护敏感数据

对于像这样的情况,我为字符串类编写了一个小扩展方法,它可能是确保字符串本身在收集之前不可读的唯一可靠方法。 显然只适用于动态生成的字符串,而不是文字。

 public unsafe static void Clear(this string s) { fixed(char* ptr = s) { for(int i = 0; i < s.Length; i++) { ptr[i] = '\0'; } } } 

我将从安全角度回答这个问题。

如果你想出于安全原因销毁一个字符串,那么可能是因为你不希望任何人窥探你的秘密信息,你希望他们可以扫描内存,或者在页面文件中找到它或者如果计算机是被盗或以其他方式受到损害。

问题是,一旦在托管应用程序中创建了System.String,您就无法做很多事情。 可能有一些偷偷摸摸的方式做一些不安全的reflection和覆盖字节,但我无法想象这样的事情是可靠的。

诀窍是永远不要把信息放在一个字符串中。

我曾经为一些公司笔记本电脑开发的系统曾经有过这个问题。 硬盘没有加密,我知道如果有人拿了一台笔记本电脑,那么他们可以轻松扫描它以获取敏感信息。 我想保护密码免受此类攻击。

我解决它的方式是:我通过捕获文本框控件上的按键事件将密码放在一个字节数组中。 文本框从不包含星号和单个字符。 密码在任何时候都不会以字符串forms存在。 然后我对字节数组进行哈希处理并将原始数据归零。 然后使用随机硬编码密钥对哈希进行异或,这用于加密所有敏感数据。

在所有内容都加密后,密钥被清零。

当然,一些数据可能以明文forms存在于页面文件中,并且也可能检查最终密钥。 但没有人会偷密码!

没有确定的方法可以从内存中清除字符串( System.String )的所有痕迹。 您唯一的选择是使用字符数组或 SecureString对象。

这完全由垃圾收集器来处理。 您可以通过调用GC.Collect()强制它运行清理。 来自文档:

使用此方法尝试回收所有无法访问的内存。

所有对象,无论它们在记忆中存在多长时间,都被考虑收集; 但是,不会收集托管代码中引用的对象。 使用此方法强制系统尝试回收最大可用内存量。

那是你能让我想到的最接近的!!

限制内存中字符串对象生命周期的最佳方法之一是将它们声明为最内层范围内的局部变量,而不是类上的私有成员变量。

对于初级开发人员来说,在类本身上声明其字符串’ private string ... ‘是一个常见的错误。

我也看到有经验的有经验的开发人员试图在私有成员变量中缓存一些复杂的字符串连接(a + b + c + d …),这样他们就不必继续计算它。 重大错误 – 几乎没有时间重新计算它,临时字符串几乎立即在第一代GC发生时被垃圾收集,并且通过缓存所有这些字符串吞噬的内存只是从可用内存中取出更重要的项目,如缓存的数据库记录或缓存页面输出。

一旦不需要,将字符串变量设置为null。

 string s = "dispose me!"; ... ... s = null; 

然后调用GC.Collect()来撤销垃圾收集器,但GC不能保证会立即收集字符串。