4

这会覆盖我的字符串的内容:

unsafe
{
    fixed (char* chars = str)
    {
        for (int i = 0; i < str.Length; i++)
            chars[i] = '1';
    }
}

背景是我正在使用NetworkCredientials,您在其中使用普通的 old 设置密码System.String。如果可能的话,我想在之后“清除它”。欢迎任何有关如何执行此操作的建议,但主要问题是了解是否fixed真的可以让我访问底层 char 数组。谢谢!

编辑

我想了解这里发生了什么- 如果字符串对象是不可变的,并且fixed不让对象移动,那么发布的代码中发生了什么?这些字符被写入哪里?

4

3 回答 3

12

改用NetworkCredentials构造函数重载SecureString。过载的全部原因是为了避免这个问题。你不应该去尝试改变System.String实例。(反射当然可以,但应该避免。)

于 2013-11-06T10:29:12.553 回答
6

System.String是不可变的,所以你不能修改它。

来自 MSDN:

字符串是不可变的——字符串对象的内容在创建对象后不能更改,尽管语法使它看起来好像您可以这样做。

如果出于安全原因需要删除字符串,请尝试查看SecureString

事实上,你的代码改变了字符串,你可以在这里看到来自 Eric Lippert 的答案:String immutability in C#

您可以创建 CLR 对其强制不变性的类型。然后,您可以使用“不安全”来关闭 CLR 强制机制。这就是为什么“不安全”被称为“不安全”——因为它关闭了安全系统。在不安全代码中,如果您足够努力,进程中的每个内存字节都可以写入,包括不可变字节和 CLR 中强制不变性的代码。

如果您真的受限于没有 . 的 C# 版本SecureString,那么您必须使用不安全的代码。但也许最好的解决方案是更努力地更改版本。

于 2013-11-06T10:28:10.070 回答
2

我想了解这里发生了什么 - 如果字符串对象是不可变的,并且固定不让对象移动,那么发布的代码中发生了什么?这些字符被写入哪里?

仅当您遵守规则时,字符串才是不可变的。在这里,您实际上是在使用不安全的代码来改变字符串。(甚至可以使用“安全”的代码,因为它通过但以其他方式弯曲规则,例如通过反射peverify调用非公共方法或滥用联合结构。)AppendInPlace

像这样打破规则是危险的。它可能会干扰字符串实习。它可能会破坏 .NET 运行时所依赖的内存位置,例如存在于每个 .NET 对象开头的 TypeHandle 和 syncblk 字节。等等。

于 2013-11-06T10:44:38.953 回答