Comments 15
В Rust, по-хорошему, в 99% случаях, получить segmentation fault программист может, только если сам явно указал unwrap и просто забил на этот случай.
На всякий уточню что сам по себе .unwrap()
(или, допустим, попытка доступа по недействительному индексу в массиве) в Rust может привести только к панике — аварийному завершению приложения, но не к ошибке сегментации. Последнюю получить можно только если в коде используются unsafe блоки.
Понятно что и то, и другое это падения и для конечного пользователя в целом одинаково неприятны, но с точки зрения отладки разница огромна — паники детерминированы, а порча произвольных кусков памяти (причина сегфолтов) может портить совершенно разную память, включая и ту что вообще не приведет к явному падению в месте ошибки, но аукнется где-то потом.
Короче, segfault, не так уж и страшен в подавляющем большинстве случаев. Это как необработанное исключение в питоне. Обычно сразу видно в чем проблема.
Я согласен что исправить ошибку сегментации, которая возникла из-за одной неправильной операции (т.е. когда в стеке вызовов отладчик прямо показывает место непосредственного косяка), и правда не сложно. Но не согласен что все прям так радужно:
1) Вполне реально (по крайней мере по моему опыту) столкнуться с разнесенной во времни цепочкой некорректных операций с памятью и надо будет играть в детктива вроде "ага, тут вот у нас была ссылка на уже освобожденный объект, его память уже успели частично перезаписать, но один из его указателей все еще указывал примерно в сторону массива данных, так что код в другом месте записал что хотел по этому указателю, испортив чего-то там и только вот тут уже, когда другой поток добрался до этих данных, все грохнулось".
2) Не факт, что ошибка работы с памятью вообще приведет к стабильно воспроизводимому сегфолту. Да, это случается относительно редко, но когда случается то приводит к жутчайшим гейзенбагам, которые можно отлаживать по многу дней. Что-нибудь в духе "пользователи новой версии macos сообщают что иногда приложение игнорирует настройку из конфига. воспроизвести никак не выходит. вот логи" и сиди с лупой по коду ползай, думай где что не так могло пойти. При чем, жить тихо такие ошибки могут сколько угодно и активируются какой-нибудь вообще левой ерундой, типо минорного обновления совершенно никак не связанной библиотеки.
В общем, по мне разница между необработанным исключением в питоне/паникой в расте и ошибкой работы с памятью, которая не факт что приводит к сегофолту — принципиальная.
Некоторое время назад ресерчил эту тему и остановился на pybind11 из-за наилучшей поддержки С++11,14,17 и дружбой с python GC.
Стоит ли его включить в список, или я чего-то не понимаю?
На numba написана пара очень классных ML библиотек как раз по этой причине — plug-and-play.
cffi как еще одна возможность вызывать сишный код из Python, делает кучу вещей за вас, которую нужно было делать каждый раз самостоятельно (приведение типов, импорт библиотек, етц). По скорости сравнимо с Native Extension и CTypes, по удобству использования и отсутствию жестких связок намного выигрывает у описанных решений, включая Swig
Кривая обучения и правда суровая, во многом из-за этого сообщество языка старается быть мега-дружелюбным к новичкам.
Но тут еще важно быть аккуратным с предыдущим опытом и экстраполяциями.
Частая ошибка пробующих ржавчину новичков — пробовать написать свой двусвязный список, т.к. в большинстве языков это довольно простая задача. Быстро оказывается что сделать это в ржавчине в лоб не так-то и просто из-за модели работы с памятью ("Why Writing a Linked List in (safe) Rust is So Damned Hard", "Learning Rust With Entirely Too Many Linked Lists"). Человек экстраполиует что раз такая простая задача вызывает массу сложностей, то сложные практические задачи вообще решить вообще нереально будет и забивает на раст.
Именно это я и написал — сначала попробуйте написать на Rust какой-нибудь ваш (или не ваш) алгоритм. Конечно его надо писать не по туториалу tokio.rs (опять смотрим на цель). И да, не исключено что это будет условный «двусвязный список», которого нет.
Я не противник Rust на самом-то деле. Просто написанное в статье показалось через чур оптимистичным.
Бинарные модули для Python