Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;“最后再试一次”;区块vs.“;使用;对称算法处理时的块_C#_.net_Encryption - Fatal编程技术网

C# &引用;“最后再试一次”;区块vs.“;使用;对称算法处理时的块

C# &引用;“最后再试一次”;区块vs.“;使用;对称算法处理时的块,c#,.net,encryption,C#,.net,Encryption,根据 请注意,在使用派生类时,从安全角度来看,仅在使用完对象后强制执行垃圾收集是不够的。在释放对象之前,必须显式调用对象上的Clear方法以清除对象中的任何敏感数据。请注意,垃圾收集不会将收集对象的内容归零,而只是将内存标记为可用于重新分配。因此,垃圾收集对象中包含的数据可能仍然存在于未分配内存中的内存堆中。对于加密对象,此数据可能包含敏感信息,如密钥数据或纯文本块 NET Framework中所有保存敏感数据的加密类都实现了一个Clear方法。调用Clear方法时,Clear方法会用零覆盖对象

根据

请注意,在使用派生类时,从安全角度来看,仅在使用完对象后强制执行垃圾收集是不够的。在释放对象之前,必须显式调用对象上的Clear方法以清除对象中的任何敏感数据。请注意,垃圾收集不会将收集对象的内容归零,而只是将内存标记为可用于重新分配。因此,垃圾收集对象中包含的数据可能仍然存在于未分配内存中的内存堆中。对于加密对象,此数据可能包含敏感信息,如密钥数据或纯文本块

NET Framework中所有保存敏感数据的加密类都实现了一个Clear方法。调用Clear方法时,Clear方法会用零覆盖对象内的所有敏感数据,然后释放对象,以便可以安全地对其进行垃圾收集。当对象归零并释放后,应调用Dispose方法,并将disposing参数设置为True,以处置与该对象关联的所有托管和非托管资源

我从中得到的是,我必须使用try finally块来处理我的算法,如下所示:

SymmetricAlgorithm symmetricAlgorithm = SymmetricAlgorithm.Create()
try 
{
     //stuff
}
finally
{
    symmetricAlgorithm.Clear();
    symmetricAlgorithm.Dispose(true)
}
如果使用块,我将无法使用更简洁的

using (var symmetricAlgorithm = SymmetricAlgorithm.Create())
{
    //do stuff
}

因为它不会清除记忆。它只会将其标记为收藏。对吗?感谢您的帮助。

以下是Clear方法的实现方式(来自Reflector):

因此,您可以使用

[调用Dispose]将仅将其标记为收集。对吗

不,这是不对的。你对“处置”的作用有误解。这是一个非常普遍的误解

请允许我非常清楚地说明这一点:Dispose本身与垃圾收集完全无关。Dispose没有任何特殊之处,在任何其他名称的方法中都无法做到。许多人相信以下神话:

  • 在实现IDisposable接口的对象上调用Dispose方法会“标记”要收集的对象
  • 垃圾收集器在收集对象时调用IDisposable.Dispose
这些神话都不是真的

事实是:

  • 处理完对象后调用“Dispose”是一种约定,旨在确保在垃圾回收器开始清理与对象关联的托管内存资源之前清理非托管资源

  • 垃圾收集器仅根据对象的任何引用是否可以通过已知的活动对象访问来决定何时收集对象。调用“Dispose”或任何其他方法都不会使对象无法访问

  • 垃圾收集器(有时)会在对象被收集前不久对其调用“终结器”(也称为“析构函数”)。按照惯例,对象的作者通常会选择将对象的终结与其处置相同。但是,这只是一个惯例

  • 按照惯例,刚被释放的对象应该告诉垃圾收集器,当该对象最终变得不可访问时,GC可以安全地跳过该对象的终结


“Dispose”只是一种方法。如果该方法碰巧告诉GC一堆东西,比如“顺便说一句,有人已经完成了这个对象”,那么该方法可以自由地这样做。“处置”没有内在的魔力。您可以编写您自己的方法“MyDispose”和您自己的接口“IMyDisposable”,它们也可以做同样的事情;GC既不知道也不关心您选择了什么约定来组织代码,以便尽早释放非托管资源。

顺便说一句,using语句的末尾不会将对象标记为colleciton。它应该释放对象持有的任何非托管资源。一旦不再引用对象(包括堆栈或寄存器),就会发生集合。这是我所期望的。如果
Clear
Dispose
都有细微不同的语义,那就很奇怪了。通常,这些功能是等效的(例如流上的
Close
Dispose
)。感谢您的确认。
在Dispose中没有固有的魔力
——关于终结和垃圾收集,是的。但值得指出的是,
IDisposable
是“特殊的”,因为它是使用(…){}
语句支持类型作为
目标所需的接口。。。这可能是为什么有些人认为它在垃圾收集方面有一些特殊处理的原因。@LBushkin:我同意,这确实是原因之一。很多人没有意识到“using”只不过是一个“finally”块的C#语法糖,其中包含一个Dispose调用。Eric,您是否试图指出这样一个事实,即资源获取中声明的局部变量是只读的,并且using语句可以正确处理值类型/引用类型/动态类型?using语句还有什么“更多”的地方吗?如果Clear只在其主体中调用Dispose,那么使用“using”语句调用Dispose就足够了。@SolutionYogi:虽然我大体上完全同意您的观点,但请编写代码,使其(1)清晰和(2)清晰做的正是文档中推荐的——提供加密类型的人非常有安全意识,不会做出导致常用模式突然开始悄无声息地中断的更改。我们有理由期待Dispose和Clear永远是同义词。
public void Clear()
{
    ((IDisposable) this).Dispose();
}