我听过有关这个主题的相互矛盾的故事,我正在寻找一点清晰。
如何立即处理string
对象,或者至少清楚地处理它?</ p>
答案 0 :(得分:7)
这取决于。默认情况下,文字字符串为interned,因此即使您的应用程序不再引用它,也不会收集它,因为内部实习结构会引用它。其他字符串就像任何其他托管对象一样。一旦它们不再被您的应用程序引用,它们就有资格进行垃圾回收。
答案 1 :(得分:6)
如果您需要保护字符串并且能够在需要时进行处理,请使用System.Security.SecureString
类。
答案 2 :(得分:5)
我为这种情况写了一个字符串类的扩展方法,它可能是确保字符串本身在收集之前不可读的唯一可靠方法。显然只适用于动态生成的字符串,而不是文字。
public unsafe static void Clear(this string s)
{
fixed(char* ptr = s)
{
for(int i = 0; i < s.Length; i++)
{
ptr[i] = '\0';
}
}
}
答案 3 :(得分:3)
我将从安全角度回答这个问题。
如果你想出于安全原因销毁一个字符串,那么可能是因为你不希望任何人窥探你的秘密信息,你希望他们可以扫描内存,或者在页面文件中找到它或者是计算机被盗或以其他方式受到损害。
问题是,一旦在托管应用程序中创建了System.String,您就无法做很多事情。可能有一些偷偷摸摸的方式做一些不安全的反射和覆盖字节,但我无法想象这样的事情是可靠的。
诀窍是永远不要把信息放在字符串中。
我曾经使用我为某些公司笔记本电脑开发的系统进行过一次这个问题。硬盘没有加密,我知道如果有人拿了一台笔记本电脑,那么他们可以轻松扫描它以获取敏感信息。我想保护密码免受此类攻击。
我使用它的方式是:我通过捕获文本框控件上的按键事件将密码放在字节数组中。文本框从不包含星号和单个字符。密码在任何时候都不会以字符串形式存在。然后我对字节数组进行哈希处理并将原始数据归零。然后使用随机硬编码密钥对哈希进行异或,这用于加密所有敏感数据。
在所有内容都加密后,密钥被清零。
当然,一些数据可能以明文形式存在于页面文件中,并且也可能检查最终密钥。但没有人会偷密码!
答案 4 :(得分:2)
这完全由垃圾收集器来处理。您可以通过调用GC.Collect()
强制它进行清理。来自文档:
使用此方法尝试回收所有 无法访问的内存。
所有对象,无论多长时间 他们一直在记忆中 考虑收集;然而, 托管中引用的对象 代码未收集。用这个 迫使系统尝试的方法 收回最高金额 可用内存。
那是你最让我想到的地方!!
答案 5 :(得分:2)
没有确定的方法可以清除内存中的所有字符串(System.String
)。您唯一的选择是使用一个字符数组或一个SecureString
对象。
答案 6 :(得分:1)
限制内存中字符串对象生命周期的最佳方法之一是将它们声明为可能的最内层范围内的局部变量,而不是作为类上的私有成员变量。
初级开发人员在课堂上声明他们的字符串“private string ...
”是一个常见的错误。
我也看到有经验的有经验的开发人员试图在私有成员变量中缓存一些复杂的字符串连接(a + b + c + d ...),因此他们不必继续计算它。重大错误 - 几乎没有时间重新计算它,临时字符串在第一代GC发生时几乎立即被垃圾收集,并且通过缓存所有这些字符串吞噬的内存只是从更重要的项目(如缓存的数据库记录)中获取可用内存或缓存的页面输出。
答案 7 :(得分:-3)
一旦不需要,将字符串变量设置为null。
string s = "dispose me!";
...
...
s = null;
然后调用GC.Collect()
来撤销垃圾收集器,但GC不能保证会立即收集字符串。