Комментарии 69
Реверс-инжиниринг не является взломом, хоть и часто используется при взломе.
Копирасты продавили изменения в законодательствах большинства стран, и теперь реверс-инжиниринг по юридическим последствиям стоит в одном ряду со взломом.
А раньше и реверс, и даже патчинг кода был в ряде случаев разрешён. Например, для обеспечения запуска на имеющемся у реверсера железе.
Там используется слово "hacked", которое в английском имеет более широкий смысл, не только негативный. В данном случае по смыслу близко "встроил в компилятор C++ 28-летней давности"...
"вкорячил в компилятор C++ 28-летней давности"
И даже, судя по всему, не ничего не делал с компилятором, а всего лишь написал свои реализации служебных процедур ("хуков"), вызовы которых компилятор генерирует на try/catch/throw.
Я такое делал для MS VC++, который в отладочном режиме умеет вставлять вызовы служебных процедур, проверяющих целостность служебных же данных. Стандартные реализации тянут за собой изрядный объем кода из libc, который не умеет работать в ядре, поэтому бедняги из MS во всех своих ядерных модулях этой возможностью не пользуются, а я уже двадцать лет пользуюсь во весь рост. :)
Корявый перевод слова hack.
Боже мой, когда уж стюардессу-то закопают. Имею в виду Watcom.
Очень хорошая стюардесса, что ж вы так
Откапывать и откапывать? ;-)
Подтверждаю, не так давно им вполне коммерческую халтурку сделал :) Все эти современные полупрозрачные графонии и прочие рюшечки, тупо подцепил апи директных дров образца тыща поросятого года и всё кинулось мигать, сверкать и щёлкать так, как заказчик хотел :) А 64 бита там не требовалось, некуда и незачем.
Жив курилка!
Ладно, но потом - закопать!
Если в архитектуре используется обработка исключение как обработка ошибок, что-то пошло не так.
Wacom ,кстати был оберткой вокруг Си, и в каких-то версиях там бы Сишные структурированные исключения... он копал не в ту сторону ?
Если в архитектуре используется обработка исключение как обработка ошибок, что-то пошло не так.
Можете поподробнее раскрыть свою мысль? А то мне кажется, что по вашему мнению, на исключениях обработку ошибок делать неправильно.
Ну вот в Go возвращают errno на каждом шагу и гордятся этим.
"Возвращают errno" это оксюморон. errno в C это глобальная переменная, которая неявно модифицируется функцией, а не возвращаемое значение. И даже если воспринимать "errno" в широком смысле как "код ошибки", то вы неправы, потому что в Go в качестве ошибки можно возвращать (и на практике возвращаются) не только числа, а любые произвольные объекты с детальной информацией.
errno вполне может быть оберткой вокруг функции, афайк, т.к. требует локальности по отношению к потоку. Правильнее конечно сказать устанавливает. https://man7.org/linux/man-pages/man3/errno.3.html
если код не использует стронние библиотеки, то не надо допускать исключения в своем коде,
если вы вызываете функции сторонних библиотек, то желательно не допускать условия при которых функции завершаются с исключениями
надо, по мере сил, пытаться не допускать ошибок, которые вызывают исключения, а не наварачивать "модную" обработку ошибок на исключениях, неужели вы этого не знаете?
Ну и как мне открыть файл без вероятности исключений?(замена исключения на errno не рассматриваем)
https://medium.com@cummingsi19933/the-operation-result-pattern-a-simple-guide-fe10ff959080
На всех проектах, где есть either, работать с апи вообще желания нет. Посмотри на kotlin coroutines, dart async. Тут всё сделано для того, чтобы было удобно с исключениями работать. В то же время, если тебе надо сделать несколько последовательных операций с Either, то делай код лесенкой. Хотя мог бы в 1 try catch обернуть
А как открытие файла связано с исключениями? В Си++ там все на битах состояния ( good, bad, fail, eof)
Очень сильное утверждение. Но я пожалуй продолжу разрабатывать нормально
Неправильно. Есть паттерн result. В Rust это класс Result, в Scala и Haskell - Either, например. Логика обработки ошибок в идеале должна крутиться вокруг них, так как возможные ошибки вписываются в контракт функции, как и обязательность их обработки. Исключения ломают контракт функций - это по сути еще одно возвращаемое значение, не вписанное в сигнатуру. В Java пытались это решить, сделав декларируемые исключения, но это оказалось неудобным (особенно в свете функционального программирования).
Причем тут Rust, Scala и прочие языки программирования? Давайте притянем за уши еще Брайнфак, в котором обработки ошибок вообще нет.
Обсуждается компилятор C++, в котором исключения архитектурно предназначены в том числе и для обработки ошибок.
Мне показалось что речь шла не о вреде исключений вообще, а именно на уровне архитектуры - взаимодействия компонент. Есть какой то API, есть протокол взаимодействия, и вдруг оттуда прилетает эксепшен. В вводе выводе эксепшены удобны, но их область распространения должна быть ограничена, иначе что за прикол нажать кнопку на плеере и получить окошко что у Васи usb диск отмонтирован.
Я тоже не понял комментарий @MiyuHogosha, поэтому и попросил уточнить его возражения. Исключения сами по себе - это просто инструмент для реализации алгоритма, и не более.
Естественно, функции Сишной библиотеки не должны выбрасывать исключений, даже если они используются внутри компонент в самой библиотеке. Но это не означает, что "Если в архитектуре используется обработка исключение как обработка ошибок, что-то пошло не так."
Я парафразировал Мейерса. Анархист и нв13 даже привелии некоторые из его аргументов. А примеров что у него, что на практике - сотни. Использование исключений оголяет множество подводных камней с RAII, в стандарт даже вносились изменния только ради исправления безвыходных ситуаций, см make_unique или порядок инициализации аргументов функции.
Использование исключений оголяет множество подводных камней с RAII, ...
При реализации RAII в С++ есть подводные камни, которые вскрылись при использовании исключений и ... что? Как по мне, так наоборот, благодаря исключениям были исправлены UB, что сделало поведение программы более детерминированным.
Далеко не всегда вызов деструктора исключает UB. В ряде случаев
Ну и подготовка функции к обработке исключений (даже если они не произошли) - не бесплатная операция. Можно еще и о подстановках функций забыть.
А уж отлаживать то месиво которое получается, никому не позавидуешь. Когда-нибудь пробовали отлаживать программу которая производи 30-40 исключений в секунду? ( и не больше. это было практически близко к пределу производительности - на выход из исключения тратились десятки миллисекунд ) Мне довелось, удовольствие еще то. А в gdb без исходника вообще невозможно. Если же у вас фреймворк который вызывает функцию со стертым типом - вроде Qt или async или прочих - то там можно нарваться на UB при выходе за границу обработчиков. Поэтому Qt ловит все исключения и выкидывает из программы с текстом ошибки сводящейся к "Ты не прав, используя исключения тут и не обрабатывая".
Exception как control flow нарушает контракты и гарантии используемых функций и объектов в ООП. Поэтому стандартная библиотека выбрасывает исключения только при обнаружении ситуаций, где пользователь, т.е. программист, заведомо пошел на нарушение контракта первым. Т.е. у нас кончилась память, мы попытались разыменовать итератор end() и т.д. Т.е. те случаи, которые обычно возникают когда либо программа , либо исходные данные неверны.
Именно. А еще хуже, что в процессе какой-то файл не был закрыт, ибо этот код скипнули.
Нигде не сказано что они прдназначены для обработки ошибок. они предназначены для обработки exception, что есть слово-враг переводчика, имеющнее еще одно , узко-специализированное значение - удолетворенный протест. Это событие, требующее немедленной реакции без предпринятия каких либо других действий. Обработка состояний ошибок может быть рутинной логикой, в случае исключений программа не может работать дальше и должна занятьсяконтролем повреждений.
в случае исключений программа не может работать дальше и должна заняться контролем повреждений
Да где вы этого начитались?
Исключение, это не ошибка в программе. Исключение, это одна из базовых архитектурных конструкций для реализации алгоритма. Поведение при исключении строго детерминировано и программа продолжает свое выполнение (зависит от реализованного алгоритма), в отличии от Segmentation Fault, при возникновении которого программа просто падает.
С помощью исключений, можно обрабатывать логические ошибки, но никто не запрещает их обрабатывать их с помощью кодов возврата.
Да где вы этого начитались?
Каноническое определение исключения скомпилировано в Вики
The definition of an exception is based on the observation that each procedure has a precondition, a set of circumstances for which it will terminate "normally".[1] An exception handling mechanism allows the procedure to raise an exception[2] if this precondition is violated,[1] for example if the procedure has been called on an abnormal set of arguments. The exception handling mechanism then handles the exception.
В большинстве случает реализация исключений такова, что она стоит в сотни, тысячи, десятки тысяч больше циклов чем проверка какой-то thread-local переменной (ака errno). При этом, т.к. это требует установки обработчиков, прерываний, семафоров или как там реализованы исключения на данной платформе ДО совершения действия, обработка исключений не бесплатна даже если она не произошла. Это можно увидеть в коде, выданном компилятором.
Исключение, это не ошибка в программе. Исключение, это одна из базовых архитектурных конструкций для реализации алгоритма.
Где ВЫ это прочитали. Вы противоречите примерно всему что написано в канонической литературе. Или путаете два вида исключений. Было такое расширение для Си, перетянутое в Си++ - структурные исключения (Structured Exception Handling). Их в таком качестве пытались протолкнуть одно время.
Herb Sutter (https://codergears.com/Blog/?p=835):
Prefer using exceptions over error codes to report errors. Use status codes (such as return codes or errno) for errors only when exceptions cannot be used (when you don’t control all possible calling code and can’t guarantee it will be written in C++ and compiled using the same compiler and compatible compile options so that exception handling will work), and for conditions that are not errors. Use other methods, such as graceful or ungraceful termination, when recovery is not required or is impossible.
Если все так плохо, почему же они существуют? А потому что не всегда вообще возможно читаемо и красиво организовать обработку при множестве критических условий на разных уровнях вложенности, появляются повторяющиеся ветвления кода из проверок. Однако за все надо платить. Бьярн одобряет возможность использования исключений, но нужно помнить что реализация исключений а) доступна не на всех платформах и это разрешено стандартом, б) "убила " разработку многих компиляторов Си++ на ряде платформ в прошлом. В том числе его собственный cfront или такой супер-эффективный компилятор как TopSpeed C++.
Bjarne Stroustrup(его FAQ https://isocpp.org/wiki/faq/exceptions):
What good can using exceptions do for me? The basic answer is: Using exceptions for error handling makes you code simpler, cleaner, and less likely to miss errors. But what’s wrong with “good old errnoand if-statements”? The basic answer is: Using those, your error handling and your normal code are closely intertwined. That way, your code gets messy and it becomes hard to ensure that you have dealt with all errors (think “spaghetti code” or a “rat”s nest of tests”).
Авторы языков Rust, Scala и Haskell сильно постарались для того, чтобы использовать их Result и Either не было больно. Но язык С++ поддерживает только исключения.
std::optional-то, может, и с 17 стандарта - но вот хотя бы метод and_then у него появился в том же стандарте, что и std::expected
Однако, в С++ лямбды писать не так удобно как в других языках, и один только and_then не может сделать использование std::expected удобным.
Чтобы конкурировать по удобству с исключениями, монаде Result нужна либо нормальная do нотация (как в Scala и Haskell), либо собственный оператор (как в Rust). В крайнем случае можно припрячь сопрограммы, но тогда непонятно как применять эту штуку в, собственно, сопрограммах.
То есть, реализовать даже в виде библиотеки невозможно?
что... в Си++ исклбчения привернули с краю в 90ые, позаимствовав идею из расширения для Си (было несколmько разных, в том числе и мелкомягкое)
Видимо вы не читали Мейерса.
Исключения - это исключительные ситуации. Вроде случая, когда вы обратились к нелегальной памяти (а значит код неверен) или у вас кончилась память. Исключения приводят к развертке стека и устранению всех созданных объектов... если код написан правильно. Это медленно, затраты недетерминированы, есть большая возмошность выстрела граблей в ногу. Существование и адекватность инвариантов глобальных объектов под угрозой. Есть причина почему популярные фреймаорки выкидывают из программы "вы не обработали исключение до выхода из слота". Возврат кода или сохранение состояния ошибки в объекте более предпочтительны.
Исключения - это исключительные ситуации. ...
Это масло масляное. Исключение, это вполне себе конкретное и детерминированное поведение и они создаются при нормальном выполнении программы, а не возникают "по волшебству" из-за неправильного обращения к памяти или при её нехватке.
И если у вас действительно произойдет ошибка при работе с памятью, то это будет Segmentation Fault, а не исключение.
Это масло масляное.
Видно никогда стандарт не читали. "Неверно написанная программа - это программа не являющаяся верно написанной" (буквальный перевод). Такие определения в легализме обязательны для исключения (хм) ложных трактовок по принципу "не жив, не мертв".
Segmentation Fault нигде не описан как исключение по стандарту. Невозможность закончить выделение с помощью new является исключением.
Назовите мне хоть одно стандартное исключение, вызванное нормальным поведением (или написанием программы), В ряде случаев причины наполовину внешние. Например вы попытались открыть файл используя стандартную библиотеку, его нет на месте или у вас не разрешения его открывать на чтение, он не открылся. Вы начали из него читать. Это МОЖЕТ привести к исключению (если они поддерживаются иначе у вас только код ошибки). Программист в этом случае - козел, т.к. не проверил бит состояния на соответствие "нормальным" условиям проведения операции. У операции уже есть результат , вызванный нормальным поведением - возвращаемое количество считанных байт. Соответственно, все биты состояний ставятся отдельно (тот же eof), а исключение вызывается при неудаче. Это редкая ситуация, которой можно было избежать. Одной из целей исключений является обработка ситуации где состояние объектов может быть аварийным и их уничтожение нужно гарантировать.
Не надо писать логику на исключениях, а обработка ошибок - нормально.
В случае работы с вводом\выводом, например сокетами или файлами обработка кодов ошибок и есть часть логики, см. POSIX коды ошибок не являющиеся ошибками. Если вы под обработкой ошибок подразумеваете аварийные ситуации - да, это и есть назначение исключений. В действительности исключение - это неверный устойчивый перевод. Оно использовалось в смысле английского легализа - подтвержденный акт изъявления протеста в суде, когда сказанное должно быть проигнорированно (см. witnesses whose authority is beyond exception).
Watcom же жив в виде Open Watcom с открытым исходным кодом и до сих пор поддерживает DOS.
Ну как жив? Учитывая, что он по своей природе не поддерживает 64-разрядный код, то это уже не очень-то жизнь.
Коллега, я тоже не понимаю, зачем там что-то бинарное взламывать, если можно просто перейти на открытое решение.
Рубрика: "Угадай автора новости по заголовку".
У самурая нет цели, только путь.
Но зачем?
О, Ватком! С середины 90-х его не видел :)
взломал
Какой невероятно отвратительный перевод слова "hack". Не умеете переводить - не беритесь.
Проблема Go не в отсутствии исключений, а в отсутствии sum types и сахара для пробрасывания, по типу ?
в Rust или do notation в Haskell. Пробрасывание по значению не обязательно должно быть вербозным. В том же расте высокоуровневый код выглядит так же, как аналогичный на языке с эксепшнами, только приправленный парочкой ?
. Особенно если используется anyhow. И при этом отсутствуют все недостатки эксепшнов. Код легко композируется и для каждой функции по сигнатуре понятно, может ли она вернуть ошибку.
Sum types в Go правда тоже не планируются, но это уже упрямость и ошибка авторов. Такая же, как отсутствие дженериков (до недавних пор) и повторение the billion dollar mistake.
Я не очень понял, при чём тут "взломал" и "реверс". Код Watcom же открыли 20 лет назад?
Разработчик взломал компилятор C++ 28-летней давности, чтобы проект поддерживал исключения