LINUX.ORG.RU
ФорумTalks

Как в русте борются с переполнением стека?

 , программировай


0

5

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

★★★★★

Последнее исправление: Syncro (всего исправлений: 2)
Ответ на: комментарий от ya-betmen

Stack - это структура данных, работающая по принципу LIFO. Последний элемент, который был помещен в стек, будет первым извлеченным. В Rust все данные размер которых известен на этапе компиляции и не изменяется во время выполнения программы, обычно хранятся на стеке. Это включает примитивные типы (как i32, f64), фиксированные массивы, кортежи с элементами известного размера и структуры без динамических элементов.

Syncro ★★★★★
() автор топика

Разве это не еррорпрон от которого все страдали 20лет назад с рандомно вылетаюшими программами?

Прямо рандомно?

Как безопасносте помогает решать подобные кейсы реального использования?

Никак. Проблема исчерпания памяти нерешаема. Другой вопрос, что падает корректно, сообщая об ошибке. А не с сегфолтом.

$ cat overflow.rs 
fn f(n: u64) {
  println!("{}\n", n);
  f(n + 1)
}

fn main() {
  f(0)
}
$ rustc overflow.rs     
warning: function cannot return without recursing
 --> overflow.rs:1:1
  |
1 | fn f(n: u64) {
  | ^^^^^^^^^^^^ cannot return without recursing
2 |   println!("{}\n", n);
3 |   f(n + 1)
  |   -------- recursive call site
  |
  = help: a `loop` may express intention better if this is on purpose
  = note: `#[warn(unconditional_recursion)]` on by default

warning: 1 warning emitted

$ ./overflow > /dev/null

thread 'main' (1335857) has overflowed its stack
fatal runtime error: stack overflow, aborting
[1]    1335857 abort (core dumped)  ./overflow > /dev/null
hateyoufeel ★★★★★
()
Ответ на: комментарий от madcore

а кто тебе сказал, что там не возникает сегфолта?

Да, ты прав. Я проверил в GDB, там свой обработчик сигнала вставлен.

hateyoufeel ★★★★★
()
Ответ на: комментарий от madcore

Там специальная guard page заводится в конце стека, она в память не замаплена и при обращении к ней срабатывает сегфолт.

pftBest ★★★★
()
Ответ на: комментарий от seiken

до чего прогресс дошёл, какой-нить турбопаскаль такое умел лет 40 на зад
да и тут ничто не мешает повесить свой обработчик исключения

madcore ★★★★★
()
Ответ на: комментарий от madcore

Да, не является, но раст гарантирует что она всегда будет. Я уже плохо помню, но на какой-то платформе был баг что guard страница не создавалась и ради этого фикса даже отдельный минорный релиз выпустили.

pftBest ★★★★
()

все страдали 20лет

Растовики решили эту проблему путём несуществования раста 20 лет назад.

apt_install_lrzsz ★★★
()
Ответ на: комментарий от pftBest

gp - это вообще функция ос, а все те детали зависят от архитектуры, модели памяти, abi итп
для раста работают те же самые механизмы mmu

madcore ★★★★★
()

Разве это не еррорпрон от которого все страдали 20лет назад с рандомно вылетаюшими программами?

А потом придумали ulimit -s?

ratvier ★★
()
Ответ на: комментарий от hateyoufeel

ну рекурсия это не совсем то, она переполняет стек даже если явной работы с памятью не происходит и ее могут детектить линтеры и компиляторы

Syncro ★★★★★
() автор топика

Разве это не еррорпрон от которого все страдали 20лет назад с рандомно вылетаюшими программами? Как безопасносте помогает решать подобные кейсы реального использования?

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

X512 ★★★★★
()
Ответ на: комментарий от X512

будто раст это может как-то гарантировать

начнёт записывать в чужую память

в чужую - это уж слишком
попортись свою может, и «защита» от переполнения тут никак не поможет при флат-модели памяти

madcore ★★★★★
()
Ответ на: комментарий от madcore

попортись свою может, и «защита» от переполнения тут никак не поможет при флат-модели памяти

Не может. Невозможность перепрыгивания за защитную страницу стека гарантируется в Rust. Она даже в сишной функции alloca гарантируется путём пробы на чтение каждой страницы выделяемой на стеке памяти. Это не просто SUB RSP, xxx.

X512 ★★★★★
()
Ответ на: комментарий от X512

оно гарантирует только если ты последовательно достигнешь этой границы, и раст тут никаким боком
но так как у нас общее адресное пространство стека и данных, ничто не мешает случайно перескочить «заглушку» при обращении

madcore ★★★★★
()
Ответ на: комментарий от madcore

ничто не мешает случайно перескочить «заглушку» при обращении

Мешает. Rust не позволяет без unsafe обратится по произвольному адресу либо выйти за границу массива. При выделении больших структур или массивов на стеке обязательно осуществляется проба на чтение каждой страницы (обычно 4096 байт) выделенной памяти. Если проба на чтение попала на защитную страницу в конце стека, будет исключение и программа упадёт.

X512 ★★★★★
()
Ответ на: комментарий от madcore

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

Syncro ★★★★★
() автор топика
Ответ на: комментарий от Syncro

И где тут про то

что в русте по умолчанию все выделяется на стеке

ya-betmen ★★★★★
()
Ответ на: комментарий от X512

покажи мне хотя бы хеллоуворлд без ансейф и макросов

madcore ★★★★★
()
Ответ на: комментарий от X512

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

как эта хрень помешает мне обратиться по индексу, сформированному через rand()?

madcore ★★★★★
()
Ответ на: комментарий от Syncro

в жаве ссылочные типы всегда в куче, за ними как раз потом ходит гц подчищать.

а ссылки на эти кучные переменные по-твоему в какой памяти хранятся?

madcore ★★★★★
()
Ответ на: комментарий от madcore

Упадёт ещё при вызове функции с большим локальным массивом. Вы не успеете обратиться ни по какому индексу.

X512 ★★★★★
()
Ответ на: комментарий от madcore

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

Syncro ★★★★★
() автор топика
Ответ на: комментарий от beastie

Объясните мне, пожалуйста, что означает фраза «в русте запрещены переполнения стека»?

В мою бытность считалось, что стек - это не объект или категория языка, это способ хранения данных, который удобен для использования вызова функций и возврата. Он и используется компилятором в основном для этих целей. Сами языки обычно концепции «стек» не имеют. Исключение - язык Forth, но сейчас мы не о нём.

Или «раст» имеет такую языковую концепцию? Или когда говорят «в расте что-то есть» имеют в виду всю экосистему «раст», включая компеляцию и рантайм? Но если второе, то всегда можно запилить альтернативу «с блэкджеком и шлюхами», и раст как язык сдесь не при чём.

VIT ★★
()

Сталкивался с переполнением стека только при ошибках рекурсии (когда условие выхода не срабатывает). Его же трудно вызвать с учётом того, что на современных ОС стек умеет автоматически расти. Главное не создавать мегабайтные объекты прямо на стеке, иначе можно пролететь guard страницы. Но это нормальные люди и не делают.

KivApple ★★★★★
()

https://www.opennet.ru/opennews/art.shtml?num=64214

В новой версии Rust Coreutils: 
...
В утилите mkdir устранено переполнение стека, приводящее к аварийному завершению при создании большого (200+) числа вложенных каталогов. 
greenman ★★★★★
()
Ответ на: комментарий от beastie

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

Что конкретно Rust делает при повреждение стэка или перед ним?Падает.

Просто: в русте запрещены переполнения стека. Еретиков поддают анафеме.

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

byko3y ★★★★
()
Ответ на: комментарий от hateyoufeel

Проблема исчерпания памяти нерешаема. Другой вопрос, что падает корректно, сообщая об ошибке. А не с сегфолтом.

А если так?

fn fast_string_copy(src: &str, dest: &mut String) {
    let src_ptr = src.as_ptr();
    let len = src.len();
    let dest_vec = dest.as_mut_vec();
    dest_vec.reserve(len);
    unsafe {
        let dest_ptr = dest_vec.as_mut_ptr().add(dest_vec.len());
        ptr::copy_nonoverlapping(src_ptr, dest_ptr, len);
        dest_vec.set_len(dest_vec.len() + len);
    }
}
Вот только не надо мне рассказывать, что у вас в программах ансейфов вообще никогда не бывает.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

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

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

hateyoufeel ★★★★★
()
Ответ на: комментарий от KivApple

переполнением стека только при ошибках рекурсии

Ну, ещё на микроконтроллерах и маленьких DSP, где всего несколько КБ на стек. Один «маленький» буфер в одной функции, ещё в другой вложенной, в третьей… - и всё, стека не хватило.

Главное не создавать мегабайтные объекты прямо на стеке,…

А в расте натолкнуться на переполнение стека проще-простого:

I was trying to store a large array on the heap, the code produced a run-time error of stack overflow.

https://github.com/rust-lang/rust/issues/28008 (и т.д. по ссылкам)

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

gag ★★★★★
()
Ответ на: комментарий от seiken

извините, а когда раст-победная функция просто сама по себе, линкуется с чем-то ещё, или, прости г-ди, это модуль ведра, вы там тоже ожидаете модных сообщений от его рантайма?

madcore ★★★★★
()
Ответ на: комментарий от madcore

Линус - человек подневольный и раб своих исходников. Какой смысл с ним разговаривать?

seiken ★★★★★
()
Ответ на: комментарий от Ygor

А потом придумали java

И как начало всё тормозить…

Не нуачо железо надо-же продавать.

her_s_gory ★★
()

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

ox55ff ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)