блок "try-finally" против блока "using" при утилизации SymmetricAlgorithm - PullRequest
5 голосов
/ 30 июня 2011

Согласно документам msdn для System.Security.Cryptography.SymmetricAlgorithm

Обратите внимание, что при использовании производных классов недостаточно просто с точки зрения безопасности простовызвать сборку мусора после того, как вы закончили использовать объект.Вы должны явно вызвать метод Clear объекта, чтобы обнулить любые конфиденциальные данные в объекте, прежде чем он будет освобожден.Обратите внимание, что сборка мусора не обнуляет содержимое собранных объектов, а просто помечает память как доступную для перераспределения.Таким образом, данные, содержащиеся в объекте сбора мусора, могут все еще присутствовать в куче памяти в нераспределенной памяти.В случае криптографических объектов эти данные могут содержать конфиденциальную информацию, такую ​​как ключевые данные или блок простого текста.

Все криптографические классы в .NET Framework, которые содержат конфиденциальные данные, реализуют метод Clear.При вызове метод Clear перезаписывает все конфиденциальные данные внутри объекта нулями, а затем освобождает объект, чтобы его можно было безопасно собирать.Когда объект был обнулен и освобожден, вам следует вызвать метод Dispose с параметром распоряжения, установленным в True, чтобы избавиться от всех управляемых и неуправляемых ресурсов, связанных с объектом.

Что я получаюотсюда следует, что мне нужно использовать блок try-finally, чтобы избавиться от моего алгоритма, например так:

SymmetricAlgorithm symmetricAlgorithm = SymmetricAlgorithm.Create()
try 
{
     //stuff
}
finally
{
    symmetricAlgorithm.Clear();
    symmetricAlgorithm.Dispose(true)
}

Я бы не смог использовать более сжатый using блок

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

, потому что это не очистит память.Это будет только пометить его для сбора.Это верно?Спасибо за помощь.

Ответы [ 2 ]

17 голосов
/ 30 июня 2011

[вызов Dispose] пометит его только для сбора. Это правильно?

Нет, это не правильно. Вы неправильно понимаете, что делает «Dispose». Это очень распространенное недоразумение.

Позвольте мне быть предельно ясным в этом вопросе: «Утилизация» сама по себе не имеет абсолютно никакого отношения к сбору мусора. В «Утилизации» нет ничего особенного, чего нельзя было бы сделать ни одним другим методом. с любым другим именем. Многие люди верят в следующие мифы:

  • Вызов метода с именем Dispose для объекта, который реализует интерфейс с именем IDisposable, «помечает» объект для сбора.
  • Сборщик мусора вызывает IDisposable.Dispose при сборе объекта.

Ни один из этих мифов не является правдой.

Факты:

  • Вызов «Dispose», когда вы закончите с объектом, является соглашением , предназначенным для того, чтобы неуправляемые ресурсы были очищены перед сборщик мусора приступает к очистке ресурсов управляемой памяти , связанных с объектом.

  • Сборщик мусора решает, когда объект должен быть собран исключительно на основе того, достижима ли какая-либо ссылка на объект через известный для жизни объект. Вызов «Утилизация» или любого другого метода ничего не делает для недоступности объекта.

  • Сборщик мусора будет (иногда) вызывать «финализатор» (он же «деструктор») для объекта незадолго до его сбора. В соответствии с соглашением автор объекта обычно выбирает, чтобы финализация объекта была идентична его удалению. Но опять же, это всего лишь соглашение.

  • Как правило, объект, который только что был удален, должен сообщить сборщику мусора, что сборщик мусора может безопасно пропустить завершение этого объекта, когда он в конечном итоге станет недоступным.

«Утилизация» - это просто метод. Если этот метод сообщает GC кучу вещей, например, «кстати, кто-то уже позаботился о завершении этого объекта», метод может сделать это бесплатно. Нет волшебства, присущего «Распоряжаться». Вы можете написать свой собственный метод «MyDispose» и собственный интерфейс «IMyDisposable», который делал то же самое; GC не знает и не заботится о том, какие соглашения вы выбрали для организации своего кода, чтобы он раньше высвобождал неуправляемые ресурсы.

11 голосов
/ 30 июня 2011

Вот как реализован метод Clear (из Reflector):

public void Clear()
{
    ((IDisposable) this).Dispose();
}

Таким образом, вы можете использовать блок using.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...