попробуйте поймать исключения в небезопасном коде

Я пишу код обработки изображений и использую С# для низкоуровневых манипуляций с пикселями. Время от времени возникает исключение accessViolationException.

Есть несколько подходов к этой типичной проблеме, некоторые считают, что код должен быть написан надежно, чтобы не было исключений нарушения доступа, и, насколько я пытаюсь, приложение работает нормально, однако я хотел бы добавить отлов попытки, чтобы если что-то было чтобы это произошло, приложение не потерпело бы слишком ужасный сбой.

До сих пор я добавил пример кода, чтобы проверить его.

unsafe
{
    byte* imageIn = (byte*)img.ImageData.ToPointer();
    int inWidthStep = img.WidthStep;
    int height = img.Height;
    int width = img.Width;
    imageIn[height * inWidthStep + width * 1000] = 100; // make it go wrong
}

Когда я пытаюсь поймать этот оператор, я все равно получаю исключение. Есть ли способ поймать исключения, сгенерированные в небезопасном блоке?

Изменить: как указано ниже, этот тип исключения больше не обрабатывается, если их проверка не включена явно путем добавления этого атрибута в функцию и добавления «using System.Runtime.ExceptionServices».

[HandleProcessCorruptedStateExceptions]
    public void makeItCrash(IplImage img)
    {
        try
        {
            unsafe
            {
                byte* imageIn = (byte*)img.ImageData.ToPointer();
                int inWidthStep = img.WidthStep;
                int height = img.Height;
                int width = img.Width;
                imageIn[height * inWidthStep + width * 1000] = 100; // to make it crash
            }
        }
        catch(AccessViolationException e)
        {
            // log the problem and get out
        }
    }

person Denis    schedule 07.11.2012    source источник
comment
некоторые считают, что код должен быть написан надежно, чтобы не было исключений нарушения доступа - мне непонятно, почему такой код, как вы написали, не может быть написан таким образом, чтобы избежать исключений.   -  person Kirk Woll    schedule 07.11.2012
comment
Итак, почему вы не можете посмотреть на исключение и исправить проблему?   -  person John Saunders    schedule 07.11.2012
comment
Исправьте чертову проблему FFs! Не закапывайте ошибку!   -  person Mitch Wheat    schedule 07.11.2012
comment
Если вы знаете, что пишете в память, вам тоже нельзя писать... конечно, вы бы исправили алгоритм...? Это явная проблема с вашим алгоритмом. Исправьте это.   -  person Simon Whitehead    schedule 07.11.2012
comment
Мета: Вместо того, чтобы минусовать его, поставьте его правильно. Вся цель этого сайта состоит в том, чтобы помочь друг другу стать лучше в том, что мы делаем. Голоса против делают мою работу за меня или плохо объясняют вопросы, а не ругают кого-то за наивную ошибку.   -  person Iain Fraser    schedule 07.11.2012
comment
Было бы неплохо позволить программе корректно завершать работу, если произойдет что-то неожиданное, и предупредить программиста об исключении во время выполнения.   -  person Denis    schedule 07.11.2012
comment
Если вы получаете нарушения прав доступа, вероятно, у вас повреждены данные. В этот момент программа должна совершить самоубийство. Единственное, что вы должны сделать в этот момент, — это зарегистрировать и, возможно, записать данные в какой-нибудь аварийный файл (НЕ сохраняйте изменения, они могут быть повреждены!)   -  person Loren Pechtel    schedule 07.11.2012
comment
@ Денис, Лорен права; нет реалистичного сценария, в котором вы должны получить нарушение прав доступа, если только у вас нет ошибки. Существует бесконечно малая вероятность того, что память повреждена или сломана, но это не та ситуация, о которой вам следует беспокоиться.   -  person Kirk Woll    schedule 07.11.2012
comment
То же самое происходит и со мной, хотя я написал код надежно. В режиме релиза исключение никогда не выбрасывается, в режиме отладки очень редко (раз в 10000+ выполнений подпрограммы). Повторная обработка того же изображения не приводит к ошибкам/исключениям. Вот почему я хочу поймать и понять, почему иногда что-то идет не так. Доступ к изображениям только для чтения.   -  person Angelo Mascaro    schedule 03.09.2019


Ответы (1)


Проверьте размеры и верните ArgumentOutOfRangeException, если параметры заставляют вас писать за пределами изображения.

AccessViolationException — это исключение из-за поврежденного состояния (CSE), а не исключение из обработки структурированных исключений (SEH). Начиная с .NET 4, catch(Exception e) не будет перехватывать CSE, если вы не укажете его с помощью атрибута. Это потому, что вы должны писать код, который в первую очередь избегает CSE. Подробнее об этом можно прочитать здесь: http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035

person Robert Rouhani    schedule 07.11.2012
comment
В ответ на ваш отредактированный ответ это не очень хорошее решение. В качестве побочного эффекта вы получите частично измененное изображение. И если предполагается, что это критично по времени, и вы вызываете метод несколько раз, обработка исключений убьет производительность. - person Robert Rouhani; 07.11.2012
comment
Согласованный. Возможно, лучше использовать это для записи в файл журнала (возможно ли это навсегда испортит данные, если это будет сделано?), а затем выйти вместо того, чтобы просто выйти без каких-либо подробностей о том, что произошло? - person Denis; 07.11.2012
comment
честно говоря, если вы просто проверите границы, все будет в порядке, поскольку вы сможете математически доказать, что не будете писать за пределами правильных границ, но если вы ДЕЙСТВИТЕЛЬНО хотите поймать здесь исключение, убедитесь, что вы только поймав AccessViolationException, выписать сообщение о порче памяти, затем Environment.Exit(1);. При проверке границ аппаратное повреждение памяти — единственное, что может вызвать нарушение прав доступа, и вероятность этого крайне мала. - person Robert Rouhani; 07.11.2012