Comments 7
То есть есть просто функция, есть @safe-функция, есть @trusted-функция, и есть @system-функция, причём чтобы оно полноценно работало надо ещё особые флажки компилятору совать? Чот кажется ребята слегка переусложнили. Вероятно также функция может одновременно быть @system и @trusted?
Rust'овая модель с "всё safe, если в явном виде не сказано иное" как-то попроще.
Нет, @safe
, @trusted
, @system
друг с другом не компонуются. По умолчанию используется @system
, и большую часть своего кода я, например, писал в этом режиме. Основная опасность — это всё-таки работа с указателями, но они редко нужны (в основном для взаимодействия с кодом на Си). Если специально не заморачиваться, ситуации выхода за пределы допустимой памяти невероятны. Ссылки на память из освобождённого стека более вероятны, и как раз написанное в статье помогает избежать проблем, но это тоже специфические случаи
Можно один раз в начале файла написать @ safe чтобы по умолчанию все функции были с этим атрибутом, но это приведет к битию линейкой по пальцам, как в расте, ибо транзитивность отслеживается. Умолчание @system
удобнее, позволяет вызывать все остальные без вопросов.
Впрочем, за атрибутный ад, что можно (хоть и не нужно) писать 5 атрибутов каждой функции, D критикуют.
В D это возможно, потому что безопасное для памяти подмножество языка не предотвращает прямой доступ к памяти как таковой.
…
Это безопасно для памяти, потому что safe D не позволяет создавать указатели int*, указывающие на нераспределённые области памяти
Не совсем понял этот момент. Можно ли в функции, не помеченной как @safe
, создать кривой указатель, а потом передать его в "безопасную" функцию?
Можно, например, создать указатель с помощью malloc, арифметикой указателей выйти за пределы выделенной области и передать это чудо в @safe
-функцию. Или прямо можно написать любую ерунду вроде void* ptr = cast(void*)0x77
и передать в @safe
-функцию, потому что @safe
-функция не будет отслеживать всё, что происходит снаружи. Так что программист по-прежнему должен быть адекватен и знать, что он делает, особенно, если это происходит за пределами @safe
В таком случае мне больше по душе подход раста, который заставляет оборачивать разыменование указателей в unsafe блоки. Но (кажется) понимаю почему так сделали.
Могу сказать, что за восемь лет жизни на D я ни разу не нарушил безопасность памяти, т.к. почти всегда мы имеем дело с D-шными массивами, по которым мы проходим с foreach, а если обратиться к несуществующему элементу, будет кинуто исключение. А трогать указатели нам нужно крайне редко, использовать же их арифметику совсем не нужно в обычном коде. Для особых случаев статья рассказывает, как последние нововведения языка помогают избегать проблем. Вспомнил: безопасность памяти я нарушал разве что тогда, когда неправильно портировал Си-шные сигнатуры функций, тогда у меня происходило нарушение работы стека
Безопасная работа с памятью в D