Код, демонстрирующий важность ограниченной области выполнения

Может ли кто-нибудь создать короткий образец, который ломается, если не применяется [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]?

Я только что просмотрел этот образец в MSDN и не могу получить его сломается, даже если я закомментирую атрибут ReliabilityContract. Наконец, кажется, всегда вызывают.


person Sam Saffron    schedule 08.07.2009    source источник


Ответы (5)


using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;

class Program {
    static bool cerWorked;

    static void Main( string[] args ) {
        try {
            cerWorked = true;
            MyFn();
        }
        catch( OutOfMemoryException ) {
            Console.WriteLine( cerWorked );
        }
        Console.ReadLine();
    }

    unsafe struct Big {
        public fixed byte Bytes[int.MaxValue];
    }

    //results depends on the existance of this attribute
    [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] 
    unsafe static void StackOverflow() {
        Big big;
        big.Bytes[ int.MaxValue - 1 ] = 1;
    }

    static void MyFn() {
        RuntimeHelpers.PrepareConstrainedRegions();
        try {
            cerWorked = false;
        }
        finally {
            StackOverflow();
        }
    }
}

Когда MyFn подвергается джиттингу, он пытается создать ConstrainedRegion из блока finally.

  • В случае без ReliabilityContract не может быть сформирована надлежащая ConstrainedRegion, поэтому генерируется обычный код. Исключение переполнения стека возникает при вызове Stackoverflow (после выполнения блока try).

  • В случае с ReliabilityContract может быть сформирована ConstrainedRegion, а требования к стеку методов в блоке finally могут быть подняты в MyFn. Исключение переполнения стека теперь возникает при вызове MyFn (до того, как будет выполнен блок try).

person jyoung    schedule 28.08.2009
comment
Обратите внимание, что этот код, кажется, корректно терпит неудачу при исключении StackOverflow, но на самом деле это не так. Если вы повредите стек, удалив большие строки и рекурсивно вызвав StackOverflow, OOM не сработает, и исключение SO не будет перехвачено. Это ограничение PrepareConstrainedRegions (афаик). See also Richter's CLR book: books.google.nl/ - person Abel; 06.01.2013

Основным драйвером для этой функциональности была поддержка строгих требований SQL Server для интеграции CLR в SQL Server 2005. Вероятно, для того, чтобы другие могли использовать и, вероятно, по юридическим причинам, эта глубокая интеграция была опубликована как хостинг API, но технические требования были SQL Servers. Помните, что в SQL Server MTBF измеряется в месяцах, а не в часах, и перезапуск процесса из-за возникновения необработанного исключения совершенно неприемлем.

Эта статья журнала MSDN, вероятно, является лучшим описанием технических требований, для которых была создана среда выполнения с ограничениями.

ReliabilityContract используется для украшения ваших методов, чтобы указать, как они работают с точки зрения потенциально асинхронных исключений (ThreadAbortException, OutOfMemoryException, StackOverflowException). Область ограниченного выполнения определяется как раздел catch или finally (или сбой) блока try, которому непосредственно предшествует вызов System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions().

System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions();
try 
{
    // this is not constrained
} 
catch (Exception e) 
{
    // this IS a CER
} 
finally 
{
    // this IS ALSO a CER
}

Когда метод ReliabilityContract используется внутри CER, с ним происходят две вещи. Метод будет предварительно подготовлен JIT, чтобы он не вызывал JIT-компилятор при первом выполнении, который может попытаться использовать саму память и вызвать собственные исключения. Также, находясь внутри CER, среда выполнения обещает не генерировать исключение ThreadAbort и будет ждать, чтобы генерировать исключение, пока не завершится CER.

Итак, вернемся к вашему вопросу; Я все еще пытаюсь придумать простой пример кода, который прямо ответит на ваш вопрос. Однако, как вы, возможно, уже догадались, для простейшего примера потребуется довольно много кода, учитывая асинхронный характер проблемы, и, скорее всего, это будет код SQLCLR, поскольку именно в этой среде CER будут использоваться с наибольшей выгодой.

person Peter Oehlert    schedule 28.08.2009
comment
Это не совсем правильно. CER также используется для SafeHandles, чтобы убедиться, что они закрыты. Это включает в себя любой P/Invoke, приводящий к SafeHandle ОС (GDI+, файлы и т. д.). Если вы начнете пропускать дескрипторы в Windows, у вас скоро возникнут проблемы. - person Jeremy; 27.06.2016

Вы запускаете образец MSDN под отладчиком? Я не думаю, что CER может работать, когда вы выполняете в отладчике, так как сам отладчик все равно меняет характер выполнения.

Если вы создадите и запустите приложение в оптимизированном режиме выпуска, вы сможете увидеть его сбой.

person jrista    schedule 27.08.2009

Хотя у меня нет конкретного примера для вас, я думаю, что вы упускаете смысл попробовать блокировать try..finally внутри методов, гарантирующих успех. Весь смысл утверждения, что метод всегда будет успешным, означает, что в отношении того, что (исключение) происходит во время выполнения, будут предприняты шаги, чтобы гарантировать, что данные, к которым осуществляется доступ, будут в допустимом состоянии, когда метод вернется. Без попытки... в конце концов, вы бы ничего не гарантировали и могли бы означать, что произойдет только половина операций, которые вы хотели. Таким образом, Cer.Success на самом деле не гарантирует успеха, он лишь утверждает, что вы, как разработчик, гарантируете успех.

Посетите эту страницу для объяснения различий между состояниями Success и MayFail в отношении метода Array.CopyTo: http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx

person Relster    schedule 09.07.2009
comment
CER в основном предназначен для защиты размещенных CLR от повреждения состояния во время отключения домена приложения и других исключительных ситуаций. Хосты, такие как SQL Server, могут инициировать грубое прерывание, во время грубого прерывания могут быть прерваны предложения finally. - person Sam Saffron; 09.07.2009
comment
Чтобы быть немного более явным, CER существуют, чтобы ДАТЬ разработчику ВОЗМОЖНОСТЬ писать код, который может защитить себя от повреждения своего собственного состояния в исключительных условиях. CER не имеет ничего общего с защитой среды CLR, она просто позволяет писать код, который может защитить сам себя. Грязный секрет в том, что в CLR 1.0/1.1 было НЕВОЗМОЖНО написать код, который мог бы успешно справляться с определенными классами исключений. - person Peter Oehlert; 28.08.2009
comment
Ссылка не работает. - person doug65536; 12.10.2016

Атрибуты CER являются средством документирования. Они влияют на то, как CLR будет выполнять код в некоторых ситуациях, но я считаю, что они (или их отсутствие) никогда не приведут к ошибке в текущих версиях .NET.

В основном они «зарезервированы для использования в будущем».

person ima    schedule 24.08.2009
comment
Несмотря на отрицательные голоса, отсутствие примеров по этому вопросу подтверждает мою точку зрения. CER не влияют на поток кода, включая блок finally. Они документируют код, поэтому фреймворк может обрабатывать его по-разному. По сути, это означает, что я не буду вызывать асинхронные исключения, вы не будете прерывать меня асинхронными исключениями. Удаление CER никогда не сломает код, хотя статистически может сделать его менее надежным. Также довольно очевидно, что CER можно использовать для гораздо большего, чем то, что в настоящее время реализуется средой выполнения. - person ima; 25.08.2009
comment
Атрибуты CER предназначены НЕ только для документации; при использовании из ограниченной области выполнения метод, помеченный ReliabilityContract, будет подготовлен перед выполнением JIT для предварительной компиляции, а память для метода будет предварительно выделена при входе в PrepareConstrainedRegions. - person Peter Oehlert; 28.08.2009
comment
Они ЯВЛЯЮТСЯ документацией. Эта документация читается и используется CLR, как я уже сказал - здесь нет противоречия. Дело в том, что короткий образец, который ломается, если не применяется [], невозможен, ничто не ломается без атрибутов CER. Становится менее надежным - да, но ничего такого, что можно было бы назвать нарушением кода. - person ima; 28.08.2009