从内存中清除一个字符

Clearing a char from memory

虽然我可以轻松地从字符串中获取字符指针:

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

我似乎无法对 char 执行相同的操作:fixed (char* c = ch) 不起作用并出现以下错误:

You cannot use the fixed statement to take the adress of an already fixed expression. Cannot implicitly convert type 'char' to 'char*'

在 C# 中我是否可以到达 char 的指针并将其删除 (= '\0')?

char 类型已经是可变的。所以你可以简单地将它的值设置为 0.

假设您有以下 char:

char c = 'a';

只需像这样将其设置为 0:

c = '[=11=]';

我在这里假设您可以直接访问 field/variable。请注意,如果您收到 char 作为方法参数,或者如果您通过调用 属性 获得它,那么您将获得原始 char 的副本。如果您将其更改为 0,那么您正在改变原始 char.

的副本

由于字符是按值传递的,因此您需要通过引用传递字符参数:

public static unsafe void Clear(ref char s)
{
    fixed (char* n = &s)
    {
        *n = '[=10=]';
    }
}

在这种情况下,不安全代码是不必要的;以上可以简单地重写为:

public static void Clear(ref char s)
{
     s = '[=11=]';
}

注意,由于扩展方法的第一个参数不能有ref修饰符,所以上面不能用作扩展方法。


另外,您的 Clear(string) 方法依赖于未定义的行为。虽然不安全的语义确实允许改变字符串,但这可能会导致意外的结果。根据语言规范(添加了重点):

Modifying objects of managed type through fixed pointers can results in undefined behavior. For example, because strings are immutable, it is the programmer’s responsibility to ensure that the characters referenced by a pointer to a fixed string are not modified.

为了说明未定义的行为,请考虑以下代码:

string d = "E";
string f = "E";
d.Clear();
Console.WriteLine(d);
Console.WriteLine(f);
Console.WriteLine("E");

由于字符串驻留,所有三个字符串都存储在相同的内存位置。结果,上面的代码打印了三个空行。

如果清除字符串的动机是从内存中清除敏感数据,则支持的方法是使用 SecureString。由于 GC 可以根据需要重新定位内存,因此无法保证清除变量的当前地址会从内存中删除对该字符串的所有引用。