Pull to refresh

Comments 15

В Rust, по-хорошему, в 99% случаях, получить segmentation fault программист может, только если сам явно указал unwrap и просто забил на этот случай.

На всякий уточню что сам по себе .unwrap() (или, допустим, попытка доступа по недействительному индексу в массиве) в Rust может привести только к панике — аварийному завершению приложения, но не к ошибке сегментации. Последнюю получить можно только если в коде используются unsafe блоки.


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

Я хотел бы заметить, что наиболее частая причина сегфолта — это неправильный указатель. Чаще всего NULL. Соответственно, gdb сразу покажет место, где был использован неправильный указатель и причина чаще всего устраняется тривиально. Я могу припомнить всего несколько случаев совсем уж случайной порчи памяти. И то, в одном случае это был код кастомного аллокатора памяти, которому сам Кнут велел обращаться к самым разным участкам памяти. А остальные случаи — это ошибки при работе с общей памятью, между несколькими ОС и/или устройствами. Тоже довольно специфичные условия.

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

Я согласен что исправить ошибку сегментации, которая возникла из-за одной неправильной операции (т.е. когда в стеке вызовов отладчик прямо показывает место непосредственного косяка), и правда не сложно. Но не согласен что все прям так радужно:


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


2) Не факт, что ошибка работы с памятью вообще приведет к стабильно воспроизводимому сегфолту. Да, это случается относительно редко, но когда случается то приводит к жутчайшим гейзенбагам, которые можно отлаживать по многу дней. Что-нибудь в духе "пользователи новой версии macos сообщают что иногда приложение игнорирует настройку из конфига. воспроизвести никак не выходит. вот логи" и сиди с лупой по коду ползай, думай где что не так могло пойти. При чем, жить тихо такие ошибки могут сколько угодно и активируются какой-нибудь вообще левой ерундой, типо минорного обновления совершенно никак не связанной библиотеки.


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

Спасибо за пояснение! Я к сожалению когда делал доклад «заболтался» и подменил понятия.

Некоторое время назад ресерчил эту тему и остановился на pybind11 из-за наилучшей поддержки С++11,14,17 и дружбой с python GC.

Про pybind11 в докладе забыли? Хотел попробовать его когда в следущий раз прийдётся подключать плюсы к питону.

Я про него просто не знал. Спасибо, если руки дойдут то попробую.
Насчёт “GDB с плагином к Python” — это может быть чересчур, если есть Visual Studio 2017, которая поддерживает mixed Python+C отладку (это есть ещё с VS 2015 вроде, но там это сильно торомозило и роняло студию, насколько я помню).
К сожалению нет у меня VS 2017. Ну и не всегда поможет, если отладку нужно произвести именно на Linux машине. Почитал про фичу, которую вы озвучили, кажется довольно годная, но к сожалению специфичная штука.
Глупый вопрос, я несколько раз использовал numba и оно просто работало (5-10x скорости в обмен на простой декоратор).
Стоит ли его включить в список, или я чего-то не понимаю?
На numba написана пара очень классных ML библиотек как раз по этой причине — plug-and-play.
Numba это же просто коспилятор Python в машинный код. На сколько я помню возможность взять и сделать ставки на каком нибудь C или Fortran не предоставляется возможным. В доке Numba видел, что свой кастомный код на C/C++ можно подключать только через cffi или ctypes, о них в докладе написано.

cffi как еще одна возможность вызывать сишный код из Python, делает кучу вещей за вас, которую нужно было делать каждый раз самостоятельно (приведение типов, импорт библиотек, етц). По скорости сравнимо с Native Extension и CTypes, по удобству использования и отсутствию жестких связок намного выигрывает у описанных решений, включая Swig

Хорошая расшифровка. Я бы добавил только обеспокоинов выбирающим Rust. Маловато написано страшных слов про него. В качестве упражнения (если хотите понять что такое Rust вообще) — попробуйте что-нибудь написать на нём. Что-нибудь из алгоритмов вашей предметной области, или просто хоть каких-нибудь алгоритмов. Я когда-то попробовал бинарный поиск с предикатом (generic разумеется). С горы в карьер это заняло у меня дня 2-3 пока оно скомпилилось (точно не помню, сейчас это уже только смутные воспоминания, пробовал в 2016ом). Такой себе learning curve. Злющий. Но написано всё верно — если оно компилится, то падает оно на 99% только в тех местах, где вы сказали ему падать. Это круто.

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


Но тут еще важно быть аккуратным с предыдущим опытом и экстраполяциями.


Частая ошибка пробующих ржавчину новичков — пробовать написать свой двусвязный список, т.к. в большинстве языков это довольно простая задача. Быстро оказывается что сделать это в ржавчине в лоб не так-то и просто из-за модели работы с памятью ("Why Writing a Linked List in (safe) Rust is So Damned Hard", "Learning Rust With Entirely Too Many Linked Lists"). Человек экстраполиует что раз такая простая задача вызывает массу сложностей, то сложные практические задачи вообще решить вообще нереально будет и забивает на раст.

Если я правильно понимаю посыл доклада и расшифровки, то из Python в Rust собираются выносить вовсе не 2+2 и «Hello, World», а именно ресурсоёмкие CPU bound задачи => «алгоритмы и структуры данных». Причём, вероятно, те, что собираются писать сами (если они есть НЕ на Rust, то Rust, разумеется, теряет ценность).

Именно это я и написал — сначала попробуйте написать на Rust какой-нибудь ваш (или не ваш) алгоритм. Конечно его надо писать не по туториалу tokio.rs (опять смотрим на цель). И да, не исключено что это будет условный «двусвязный список», которого нет.

Я не противник Rust на самом-то деле. Просто написанное в статье показалось через чур оптимистичным.
Sign up to leave a comment.