Rust код ошибки 29

Как и многие языки программирования, Rust призывает разработчика определенным способом обрабатывать ошибки. Вообще, существует два общих подхода обработки ошибок: с помощью исключений и через возвращаемые значения. И Rust предпочитает возвращаемые значения.

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

В наивной реализации обработка ошибок в Rust может выглядеть многословной и раздражающей. Мы рассмотрим основные камни преткновения, а также продемонстрируем, как сделать обработку ошибок лаконичной и удобной, пользуясь стандартной библиотекой.

Содержание

Эта статья очень длинная, в основном потому, что мы начнем с самого начала — рассмотрения типов-сумм (sum type) и комбинаторов, и далее попытаемся последовательно объяснить подход Rust к обработке ошибок. Так что разработчики, которые имеют опыт работы с другими выразительными системами типов, могут свободно перескакивать от раздела к разделу.

Основы

Обработку ошибок можно рассматривать как вариативный анализ того, было ли некоторое вычисление выполнено успешно или нет. Как будет показано далее, ключом к удобству обработки ошибок является сокращение количества явного вариативного анализа, который должен выполнять разработчик, сохраняя при этом код легко сочетаемым с другим кодом (composability).

(Примечание переводчика: Вариативный анализ – это один из наиболее общеприменимых методов аналитического мышления, который заключается в рассмотрении проблемы, вопроса или некоторой ситуации с точки зрения каждого возможного конкретного случая. При этом рассмотрение по отдельности каждого такого случая является достаточным для того, чтобы решить первоначальный вопрос.

Важным аспектом такого подхода к решению проблем является то, что такой анализ должен быть исчерпывающим (exhaustive). Другими словами, при использовании вариативного анализа должны быть рассмотрены все возможные случаи.

Сохранять сочетаемость кода важно, потому что без этого требования мы могли бы просто получать panic всякий раз, когда мы сталкивались бы с чем-то неожиданным. ( panic вызывает прерывание текущего потока и, в большинстве случаев, приводит к завершению всей программы.) Вот пример:

Если попробовать запустить этот код, то программа аварийно завершится с сообщением вроде этого:

Вот другой, менее надуманный пример. Программа, которая принимает число в качестве аргумента, удваивает его значение и печатает на экране.

Если вы запустите эту программу без параметров (ошибка 1) или если первый параметр будет не целым числом (ошибка 2), программа завершится паникой, так же, как и в первом примере.

Обработка ошибок в подобном стиле подобна слону в посудной лавке. Слон будет нестись в направлении, в котором ему вздумается, и крушить все на своем пути.

Объяснение unwrap

Тип Option

Тип Option — это способ выразить возможность отсутствия чего бы то ни было, используя систему типов Rust. Выражение возможности отсутствия через систему типов является важной концепцией, поскольку такой подход позволяет компилятору требовать от разработчика обрабатывать такое отсутствие. Давайте взглянем на пример, который пытается найти символ в строке:

Метод unwrap абстрагирует вариативный анализ. Это именно то, что делает unwrap удобным в использовании. К сожалению, panic! означает, что unwrap неудобно сочетать с другим кодом: это слон в посудной лавке.

Совмещение значений Option<T>

Получение расширения имени файла — довольно распространенная операция, так что имеет смысл вынести код в отдельную функцию:

(Подсказка: не используйте этот код. Вместо этого используйте метод extension из стандартной библиотеки.)

Rust поддерживает параметрический полиморфизм, так что можно очень легко объявить комбинатор, который абстрагирует это поведение:

Вооружившись нашим новым комбинатором, мы можем переписать наш метод extension_explicit так, чтобы избавиться от вариативного анализа:

Легко представить, что этот случай вариативного анализа не специфичен только для расширений файлов — такой подход может работать с любым Option<T> :

(Обратите внимание, что unwrap_or объявлен как метод Option<T> в стандартной библиотеке, так что мы воспользовались им вместо функции, которую мы объявили ранее. Не забудьте также изучить более общий метод unwrap_or_else ).

Таким образом, мы определили задачу нахождения расширения заданного файлового пути. Начнем с явного вариативного анализа:

Теперь мы можем переписать нашу функцию file_path_ext без явного вариативного анализа:

Тип Result

Тип Result — это способ выразить один из двух возможных исходов вычисления. По соглашению, один исход означает ожидаемый результат или » Ok «, в то время как другой исход означает исключительную ситуацию или » Err «.

Окей, давайте перейдем к примеру.

Преобразование строки в число

Стандартная библиотека Rust позволяет элементарно преобразовывать строки в целые числа. На самом деле это настолько просто, что возникает соблазн написать что-то вроде:

Неплохо, но нам пришлось написать гораздо больше кода! И нас опять раздражает вариативный анализ.

Создание псевдонима типа Result

Короткое отступление: unwrap — не обязательно зло

Мой совет сводится к следующему: используйте здравый смысл. Есть причины, по которым слова вроде «никогда не делать X» или «Y считается вредным» не появятся в этой статье. У любых решений существуют компромиссы, и это ваша задача, как разработчика, определить, что именно является приемлемым для вашего случая. Моя цель состоит только в том, чтобы помочь вам оценить компромиссы как можно точнее.

Работа с несколькими типами ошибок

Совмещение Option и Result

Давайте на время вернемся к одному из первых примеров в этой статье:

Ограничения комбинаторов

Работа с IO и анализ входных данных — очень типичные задачи, и это то, чем лично я много занимаюсь с Rust. Так что мы будем использовать IO и различные процедуры анализа как примеры обработки ошибок.

Давайте начнем с простого. Поставим задачу открыть файл, прочесть все его содержимое и преобразовать это содержимое в число. После этого нужно будет умножить значение на 2 и распечатать результат.

У нас есть три потенциальные ошибки, которые могут возникнуть:

Не смотря на все сказанное, код по-прежнему выглядит запутанным. Мастерство использования комбинаторов является важным, но у них есть свои недостатки. Давайте попробуем другой подход: преждевременный возврат.

Преждевременный return

Давайте возьмем код из предыдущего раздела и перепишем его с применением раннего возврата. Ранний return позволяет выйти из функции досрочно. Мы не можем выполнить return для file_double внутри замыкания, поэтому нам необходимо вернуться к явному вариативному анализу.

Разве это не шаг назад? Ранее мы говорили, что ключ к удобной обработке ошибок — сокращение явного вариативного анализа, но здесь мы вернулись к тому, с чего начинали. Оказывается, существует несколько способов его уменьшения. И комбинаторы — не единственный путь.

Макрос try!

Вот упрощенное определение макроса `try!:

(Реальное определение выглядит немного сложнее. Мы обсудим это далее).

Использование макроса try! может очень легко упростить наш последний пример. Поскольку он выполняет анализ вариантов и досрочной возврат из функции, мы получаем более плотный код, который легче читать:

Объявление собственного типа ошибки

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

Использование String в том стиле, в котором мы использовали его в предыдущих примерах удобно потому, что достаточно легко конвертировать любые ошибки в строки, или даже создавать свои собственные ошибки на ходу. Тем не менее, использование типа String для ошибок имеет некоторые недостатки.

Первый недостаток в том, что сообщения об ошибках, как правило, загромождают код. Можно определять сообщения об ошибках в другом месте, но это поможет только если вы необыкновенно дисциплинированны, поскольку очень заманчиво вставлять сообщения об ошибках прямо в код. На самом деле, мы именно этим и занимались в предыдущем примере.

Второй и более важный недостаток заключается в том, что использование String чревато потерей информации. Другими словами, если все ошибки будут преобразованы в строки, то когда мы будем возвращать их вызывающей стороне, они не будут иметь никакого смысла. Единственное разумное, что вызывающая сторона может сделать с ошибкой типа String — это показать ее пользователю. Безусловно, можно проверить строку по значению, чтобы определить тип ошибки, но такой подход не может похвастаться надежностью. (Правда, в гораздо большей степени это недостаток для библиотек, чем для конечных приложений).

Вместо того, чтобы использовать String как тип ошибки в нашем предыдущем примере про чтение числа из файла, мы можем определить свой собственный тип, который представляет ошибку в виде структурированных данных. Мы постараемся не потерять никакую информацию от изначальных ошибок на тот случай, если вызывающая сторона захочет исследовать детали.

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

Типажи из стандартной библиотеки, используемые для обработки ошибок

Типаж Error

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

Реализация Error довольно прямолинейна и главным образом состоит из явного анализа вариантов:

Хочется отметить, что это очень типичная реализация Error : реализация методов description и cause в соответствии с каждым возможным видом ошибки.

Типаж From

Типаж std::convert::From объявлен в стандартной библиотеке:

Очень просто, не правда ли? Типаж From чрезвычайно полезен, поскольку создает общий подход для преобразования из определенного типа Т в какой-то другой тип (в данном случае, «другим типом» является тип, реализующий данный типаж, или Self ). Самое важное в типаже From — множество его реализаций, предоставляемых стандартной библиотекой.

Вот несколько простых примеров, демонстрирующих работу From :

Итак, From полезен для выполнения преобразований между строками. Но как насчет ошибок? Оказывается, существует одна важная реализация:

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

Настоящий макрос try!

До этого мы привели такое определение try! :

Но это не настоящее определение. Реальное определение можно найти в стандартной библиотеке:

Мы уже очень близки к идеальной обработке ошибок. Наш код имеет очень мало накладных расходов из-за обработки ошибок, ведь макрос try! инкапсулирует сразу три вещи:

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

Настало время вернуться к нашему собственному типу CliError и связать все в одно целое.

Совмещение собственных типов ошибок

Чтобы исправить это, мы используем средство, с которым мы уже знакомы: создание собственного типа ошибки. Давайте вспомним код, который считывает содержимое файла и преобразует его в целое число:

Все эти реализации позволяют From создавать значения CliError из других типов ошибок. В нашем случае такое создание состоит из простого вызова конструктора значения. Как правило, это все что нужно.

Наконец, мы можем переписать file_double :

Если бы мы изменили нашу функцию file_double таким образом, чтобы она начала выполнять какие-то другие операции, например, преобразовать строку в число с плавающей точкой, то мы должны были бы добавить новый вариант к нашему типу ошибок:

И добавить новую реализацию для From :

Рекомендации для авторов библиотек

Если в вашей библиотеке могут возникать специфические ошибки, то вы наверняка должны определить для них свой собственный тип. На ваше усмотрение вы можете сделать его внутреннее представление публичным (как ErrorKind ), или оставить его скрытым (подобно ParseIntError ). Независимо от того, что вы предпримете, считается хорошим тоном обеспечить по крайней мере некоторую информацию об ошибке помимо ее строкового представления. Но, конечно, все зависит от конкретных случаев использования.

Заключение

Поскольку это довольно длинная статья, не будет лишним составить короткий конспект по обработке ошибок в Rust. Ниже будут приведены некоторые практические рекомендации. Это совсем не заповеди. Наверняка существуют веские причины для того, чтобы нарушить любое из этих правил.

Эта статья была подготовлена в рамках перевода на русский язык официального руководства «The Rust Programming Language». Переводы остальных глав этой книги можно найти здесь. Так же, если у вас есть любые вопросы, связанные с Rust, вы можете задать их в чате русскоязычного сообщества Rust.

Ошибка запуска, код ошибки 30007 – как исправить

Современные игры, все больше переходя в онлайн режимы. Но игроками часто из-за отказа в доступе к серверу приходится сталкиваться с ошибкой 30007. Этот код может еще сопровождаться следующим текстом: «easy anticheat cannot run if drivers signature enforcement has been disabled». Как следствие полный отказ от подключения к игре. Сервера при этом могут работать в штатном режиме без видимых проблем. Давайте разберемся почему появляется ошибка 30007, а ниже дадим советы по исправлению этого бага.

Ошибка запуска, код ошибки 30007 – как исправить

Причины ошибки запуска (кода ошибки 30007)

Многие игры могут получить данную ошибку при запуске игр: «Crossout», «Fortnite», «Paladins», «Dead by Daylight». Хотя из ее описания становится понятны причины – EasyAntiCheat не запущен. Все знают, что без Античита зайти на сервера нельзя – это защита от читеров, обязательное условие для создания сети с другими игроками, поэтому решение будет сводиться к включению EasyAntiCheat.

Решения по запуску

TESTSIGNING

Все манипуляции с ПК вы проводите на свой страх и риск, не всем данный способ поможет. Но может вызвать необходимость подтверждения при загрузке ПК(нажать 2 раза на ENTER). Так же у пользователей включался тестовый режим работы с ПК.

Каждая ОС имеет режим TESTSIGNING. Он предназначен для проверки новых программ без необходимости подтверждения их лицензии. Установленные драйвера и другой софт тестируются в безопасном режиме. Недостатком его становится блокировка со стороны EasyAntiCheat – ему необходимо удостовериться в лицензии устанавливаемого софта. Выходом из ситуации становится отключение TESTSIGNING.

Вторая часть решения будет уже касаться запуска Античита.

Запуск игры вместе с EasyAntiCheat

К сожалению, игроку надо лично добавить свою игру в EasyAntiCheat. Для этого на диске C находите ее корневую папку (игры). Среди множества подпапок находите, где будет четко написано «EasyAntiCheat». Тут располагается ваша система Античит.

Запускаете ее через ярлык Setup. В единственном окне с выпадающими вариантами находите вашу игру. Вне зависимости от реального положения дел, кроме «установить», все равно сначала удаляем нынешнюю версию (соответствующая категория будет слева внизу окна). Когда останется один правильный вариант «Установить», то выполняете инсталляцию. Так необходимая игра будет подключена к Античиту.

Альтернативные варианты решений

* Удалите «пиратские» патчи блокирующие доступ Античита к их правам.

* Просканируйте систему на нахождение вирусов, которые вмешиваются в работу ПК на сервере.

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

Напоследок помните про техподдержку. Команда создателей EasyAntiCheat постоянно модернизируют работу своего детища, поэтому ошибки обычное явление. Опишите суть своей проблемы в письме к разработчикам. Они в кратчайшие сроки найдут правильное решение из вашей ситуации.
Вот новый способ исправить ошибку:

Заключение

Надеюсь вы разобрались что предпринять когда появляется сообщение “Ошибка запуска” и код ошибки 30007 и знаете как устранить проблему, если у вас остались вопросы – просмотрите видео инструкцию снизу, а так же задавайте вопросы в форме комментариев или нашу группу в контакте.

Евгений Загорский

Евгений Загорский

IT специалист. Автор информационных статей на тему Андроид смартфонов и IOS смартфонов. Эксперт в области решения проблем с компьютерами и программами: установка, настройка, обзоры, советы по безопасности ваших устройств. В свободное время занимается дизайном и разработкой сайтов.

Источники:

https://habr. com/ru/post/270371/

https://itpen. ru/oshibka-zapuska-kod-oshibki-30007-kak-ispravit/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: