The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Вариант для распечатки  
Пред. тема | След. тема 
Форум Разговоры, обсуждение новостей
Режим отображения отдельной подветви беседы [ Отслеживать ]

Оглавление

Выпуск языка программирования Rust 1.33, opennews (ok), 02-Мрт-19, (0) [смотреть все]

Сообщения [Сортировка по времени | RSS]


36. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (-), 02-Мрт-19, 16:43 
Идём смотрим на пример реальной программы на этом язычке: https://gitlab.gnome.org/GNOME/fractal/issues/431 И что мы там видим? Конечно панику.
Ответить | Правка | Наверх | Cообщить модератору

40. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (38), 02-Мрт-19, 17:03 
Вроде и радоваться надо, что кривой индонигeрский код падает с паникой, а не творит делов, но там куча issues один другого лучше.
Ответить | Правка | Наверх | Cообщить модератору

46. "Выпуск языка программирования Rust 1.33"  +2 +/
Сообщение от Анонимус2 (?), 02-Мрт-19, 17:34 
Все правильно, в c/c++ получили бы чтение и использование неинициализированной памяти, в rust - паника. Именно так все и задумывалось.
Ответить | Правка | К родителю #36 | Наверх | Cообщить модератору

50. "Выпуск языка программирования Rust 1.33"  –1 +/
Сообщение от Аноним (-), 02-Мрт-19, 18:51 
В C++ было бы исключение, которое было бы поймано и обработано. В Rust исключений нет, поэтому паника на любой чих.
Ответить | Правка | Наверх | Cообщить модератору

60. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (61), 02-Мрт-19, 22:07 
У Раста панику можно обработать внутри кода, дубина.
Ответить | Правка | Наверх | Cообщить модератору

65. "Выпуск языка программирования Rust 1.33"  +1 +/
Сообщение от Аноним (-), 02-Мрт-19, 22:48 
У очередного растамана пригорело. Вам специально сделали язык, чтобы вы не игнорировали возвращаемые ошибки, так вы придумали макрос unwrap, который паникует при любой ошибке. Алсо It is not recommended to use [std::panic::catch_unwind] for a general try/catch mechanism. A panic in Rust is not always implemented via unwinding, but can be implemented by aborting the process as well.
Ответить | Правка | Наверх | Cообщить модератору

87. "Выпуск языка программирования Rust 1.33"  +1 +/
Сообщение от Аноним (41), 03-Мрт-19, 06:04 
> A panic in Rust is not always implemented
> via unwinding, but can be implemented by aborting the process as
> well.

Так это же Undefined behavior.

Ответить | Правка | Наверх | Cообщить модератору

97. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (61), 03-Мрт-19, 09:33 
В Расте гибко сделана обработка ошибок, это может быть паника, либо обработка этой паники.
В чем претензия у Вас?
Ответить | Правка | К родителю #65 | Наверх | Cообщить модератору

70. "Выпуск языка программирования Rust 1.33"  –2 +/
Сообщение от Ordu (ok), 03-Мрт-19, 00:27 
> В C++ было бы исключение, которое было бы поймано и обработано. В
> Rust исключений нет, поэтому паника на любой чих.

Оно было бы обработано примерно так:

int main() {
    try {
        real_main();
    } catch (...) {
        cerr << "Spurious exception caught. Some of us, stupid coders did something nasty.";
        return -1;
    }
}

Может быть это происходило бы не в main'е, а где-то ещё, но в любом случае, с точки зрения программы это бы выглядело как "непредвиденное исключение вылетело, единстсвенный выход -- упасть, сделав вид, что не упал".

Если тебе непонятно почему, то почитай этот самый issue, и представь себе, что программа написана на C++, что вылетает не паника, а исключение, но просто оно не обрабатывается в программе. И теперь твоя задача выбрать место, где воткнуть try {} catch (OutOfBoundException e) /*или как там это в C называется?*/. Попробуй выбрать какой-нибудь из стековых фреймов где это исключение должно быть обработано и аргументируй свой выбор.

Вот тебе код connect_gtk, на стековом фрейме которой случается попытка доступа за границы массива:

    pub fn connect_gtk(&self) {
         self.connect_headerbars();
         self.connect_login_view();
         self.connect_send();
         self.connect_markdown();
         self.connect_autocomplete();
         self.connect_directory();
         self.connect_leave_room_dialog();
         self.connect_new_room_dialog();
         self.connect_join_room_dialog();
         self.connect_account_settings();
         self.connect_invite_dialog();
         self.connect_invite_user();
         self.connect_direct_chat();
         self.connect_roomlist_search();
     }

Допустим, я заверну всё это в try {} catch (...) {}, и теперь вопрос: будет ли допустимым продолжать выполнение программы, если мы получили здесь OutOfBoundsException? Или может надо сделать несоколько блоков try, и из некоторых падать, а из некоторых продолжать? Расскажи нам, как бы здесь C++ программист обрабатывал бы исключение, и как бы ему удалось решить проблему без падения.

А если тебе до сих пор ещё неясно, то я могу копнуть ещё глубже. connect_headerbars (который вероятно был заинлайнен, и поэтому не имеет самостоятельного стекового фрейма в release) содержит такие строчки:

if let Some(decor) = set.get_property_gtk_decoration_layout() {
                 let decor = decor.to_string();
                 let decor_split: Vec<String> =
                     decor.splitn(2, ':').map(|s| s.to_string()).collect();
                 if decor_split[1].contains("close") {
                     right_header.set_show_close_button(false);
                     left_header.set_show_close_button(true);
                 } else {
                     left_header.set_show_close_button(false);
                     right_header.set_show_close_button(true);
                 }
}
Тут есть индексация в decor_splitn, которая предполагает, что там будет хотя бы два элемента, то есть что set.get_property_gtk_decoration_layout() вернула строчку, в которой есть хотя бы один символ ':'. Я не знаю, насколько такое предположение допустимо, но предположим что нет. А автор кода, очевидно считает, что да. Это предполагаемое заблуждение автора ведь никак не связано с выбором языка программирования, так? И вероятно именно оно, приводит к вылету паники или в случае C++ исключения. Расскажи как в этой гипотетической ситуации исключения C++ вместо паники rust'а сделали бы поведение программы лучше.

ps. Тут четыре выделения памяти: одно под Vec, и ещё три под String, и вся эта память освобождается обратно, после завершения внешнего if'а. И если let decor = decor.to_string(), я предполагаю, связан с тем, что gtk'шная функция возвращает что-нибудь типа CStr, и чтобы задействовать rust'овую библиотеку для работы со строками, нам необходимо сделать из него rust'овую строку (хотя всё равно я не понимаю зачем он нужен), то три оставшихся только ради того, чтобы выполнить один if с read-only доступом к decor_split[1]. И при этом, тут есть как раз потенциальная паника, если decor_split содержит меньше двух элементов.

Вместо этого ведь можно:

if decor.split(":").skip(1).map(|s| s.contains("close")).next() == Some(true) {
                     right_header.set_show_close_button(false);
                     left_header.set_show_close_button(true);
} else {
                     left_header.set_show_close_button(false);
                     right_header.set_show_close_button(true);
}

Осталось только одна пара malloc/free, тоже по-моему ненужная, но это не очень важно поскольку в любом случае это O(1) добавленной сложности для программы, а что важно, так это то, что мы больше не полагаемся на то, что splitn вернёт нам хотя бы один элемент.

Я бы объяснил им, как надо, но не знаю, как на gitlab зарегаться или залогиниться. У меня не выходит, а разбираться в чём там дело я не буду.

Ответить | Правка | К родителю #50 | Наверх | Cообщить модератору

74. "Выпуск языка программирования Rust 1.33"  –1 +/
Сообщение от Аноним (-), 03-Мрт-19, 01:37 
Ну тебя и бомбит чувак. Если я в C++ конструирую окошечко и где-то внутрях вылетело std::out_of_range, мне не обязательно уничтожать всю программу, а достаточно лишь показать пользователю сообщение об ошибке в том месте, где пользователь попросил это окошечко открыть, и продолжить дальше. Впрочем, исключение при создании окошка на C++ тулкитах - это какая-то невероятная экзотика. Это только Rust может запаниковать на такой банальной фигне.
Ответить | Правка | Наверх | Cообщить модератору

78. "Выпуск языка программирования Rust 1.33"  +1 +/
Сообщение от Ordu (ok), 03-Мрт-19, 01:48 
> Если я в C++ конструирую окошечко и
> где-то внутрях вылетело std::out_of_range, мне не обязательно уничтожать всю программу,
> а достаточно лишь показать пользователю сообщение об ошибке в том месте,
> где пользователь попросил это окошечко открыть, и продолжить дальше.

Вся эта хрень, судя по всему, происходит при старте программы и инициализации собственно графики. В каком месте и как ты будешь показывать окошечко, если графика не сынициализировалась? И что ты будешь делать дальше?

Ответить | Правка | Наверх | Cообщить модератору

77. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (-), 03-Мрт-19, 01:46 
Вот такие портянки растофанатиков почитаешь и понимаешь, что этот язык не для нормальных людей.
Ответить | Правка | К родителю #70 | Наверх | Cообщить модератору

79. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 01:48 
> Вот такие портянки растофанатиков почитаешь и понимаешь, что этот язык не для
> нормальных людей.

Да. Нормальные нам не нужны. Нормальные пускай дальше на C пишут.

Ответить | Правка | Наверх | Cообщить модератору

82. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 02:01 
> Вот такие портянки растофанатиков почитаешь и понимаешь, что этот язык не для
> нормальных людей.

А кстати, что по твоему "нормальный человек"? Это тот, кто не может прочитать более 1kb текста, разбирающего код? То есть не программист вообще?

Ответить | Правка | К родителю #77 | Наверх | Cообщить модератору

101. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (-), 03-Мрт-19, 12:05 
1kb гнилых оправданий почему программы на Rust должны паниковать вместо того, чтобы работать.
Ответить | Правка | Наверх | Cообщить модератору

104. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 12:35 
> 1kb гнилых оправданий почему программы на Rust должны паниковать вместо того, чтобы
> работать.

Заурядная техника. Не можешь оспорить, навесь ярлык. Скучно. Ты не пробовал хотя бы правила демагога на луркморе прочитать, что ли? Ну, чтоб хоть немного разнообразия в свой арсенал демагогических приёмов внести.

Ответить | Правка | Наверх | Cообщить модератору

105. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (-), 03-Мрт-19, 12:44 
Демагогия - это рассказы про безопасность раста и отсутсвие UB. В реальности растопрограммы - это минное поле паник в рантайме, дедлоков и утечек ресурсов вместе с борьбой программистов против компилятора с помощью unwrap.
Ответить | Правка | Наверх | Cообщить модератору

106. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 13:02 
> Демагогия - это рассказы про безопасность раста и отсутсвие UB. В реальности
> растопрограммы - это минное поле паник в рантайме, дедлоков и утечек
> ресурсов вместе с борьбой программистов против компилятора с помощью unwrap.

Молодец! Стоило только указать тебе на ошибки, и ты смог моментально переключиться на Bad Infinitum[1]. Такая гибкость заслуживает уважения.

[1] https://techiavellian.com/intellectual-denial-of-service-att...

Ответить | Правка | Наверх | Cообщить модератору

107. "Выпуск языка программирования Rust 1.33"  –1 +/
Сообщение от Аноним (-), 03-Мрт-19, 13:16 
Это тебе нечего мне возразить https://ru.wikipedia.org/wiki/%D0%9F%D1%...)
Ответить | Правка | Наверх | Cообщить модератору

109. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 13:32 
> Это тебе нечего мне возразить https://ru.wikipedia.org/wiki/%D0%9F%D1%...)

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

Ответить | Правка | Наверх | Cообщить модератору

113. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (-), 03-Мрт-19, 14:10 
В твоей простынке написано, что программа на расте, создающая графическое окно, обязательно должна паниковать. Я с этим и не спорю, если ты ещё не понял.
Ответить | Правка | Наверх | Cообщить модератору

114. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 14:28 
> В твоей простынке написано, что программа на расте, создающая графическое окно, обязательно
> должна паниковать. Я с этим и не спорю, если ты ещё
> не понял.

Ты читать умеешь? Там написано, что тот кто писал код не может распарсить строку вида "ключ:значение".

Ответить | Правка | К родителю #113 | Наверх | Cообщить модератору

118. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Аноним (-), 03-Мрт-19, 14:53 
Отличный повод для паники 👍
Ответить | Правка | К родителю #114 | Наверх | Cообщить модератору

121. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 15:18 
> Отличный повод для паники 👍

Слушай, может ты всё же почитаешь, что я там написал, и подумаешь головой о том, как C++ позволил бы избежать этой проблемы? Позволил бы он? Если бы автор написал бы этот свой код на всяких разных языках программирования, то в C он бы получил чтение за пределами массива, в C++/rust'е он бы получил исключение выхода за границы массива, в js и прочей нечисти такого рода, он бы прочитал несуществующее значение из массива, получил бы null или типа того, он бы получил false в результате сравнения и его код сработал бы. Правильно или не правильно -- я не знаю, всё зависит от того, должна ли быть else ветка if'а дефолтной или нет.

В C++/rust'е он бы получил исключительную ситуацию, в C++ размотку стека исключением, в rust'е паникой. Обработать эту ошибку осмысленно невозможно. Такого рода ошибки исправляются единственным способом: проверкой индекса до того, как этот индекс был использован по назначению.

Ты, я вижу, никак не можешь впитать эту идею. Я могу тебе помочь. Расскажи как бы ты, имея на руках аналогичную C++ программу, обезопасил функцию connect_gtk от подобных вылетающих исключений, вызванных тем, что тот кто писал всю эту пачку connect_* функций, позволял себе эпизодически выходить за границы массивов. Как бы ты обрабатывал такие исключения? Вот возьми и расскажи. Пока ты будешь рассказывать ты поймёшь о чём я, и тебе надоест рассказывать, ты удалишь всё написанное и опять включишь свою демагогию.

Ответить | Правка | К родителю #118 | Наверх | Cообщить модератору

123. "Выпуск языка программирования Rust 1.33"  +1 +/
Сообщение от Аноним (123), 03-Мрт-19, 16:44 
>  как C++ позволил бы избежать этой проблемы? Позволил бы он?

Разумеется! Во-первых, в C++ никому в голову не пришло бы писать подобный бред с разбором строк ad-hoc:

if let Some(decor) = set.get_property_gtk_decoration_layout() {
                 let decor = decor.to_string();
                 let decor_split: Vec<String> =
                     decor.splitn(2, ':').map(|s| s.to_string()).collect();
                 if decor_split[1].contains("close") {
                     right_header.set_show_close_button(false);
                     left_header.set_show_close_button(true);
                 } else {
                     left_header.set_show_close_button(false);
                     right_header.set_show_close_button(true);
                 }
}

это для скриптов такое поделие сойдёт, но не для кода, который должен выполняться быстро (иначе зачем мы языком для системного программирования занялись?). Во-вторых, даже если бы и пришло, в C++ подобную конструкцию всегда можно окружить try/catch блоком и выполнить сценарий по умолчанию, например:

           } else {
                     left_header.set_show_close_button(false);
                     right_header.set_show_close_button(true);
                 }

И не надо мне писать, что панику в расте можно отловить так же, как исключение в C++. Нельзя, паники в придумали расте не для этого. Но главная проблема раста даже не в этом. Проблема раста в том, что из этого кода просто не видно, что там зарыта паника.
Ответить | Правка | К родителю #121 | Наверх | Cообщить модератору

130. "Выпуск языка программирования Rust 1.33"  –2 +/
Сообщение от Ordu (ok), 04-Мрт-19, 00:49 
>>  как C++ позволил бы избежать этой проблемы? Позволил бы он?
> Во-первых, в C++ никому в голову не пришло бы писать подобный
> бред с разбором строк ad-hoc:

О, да. Я всё ждал, когда ты скажешь, что C++ программисты особенные, и они не делают таких ошибок.

> это для скриптов такое поделие сойдёт, но не для кода, который должен
> выполняться быстро (иначе зачем мы языком для системного программирования занялись?).

Речь идёт о стартапе программы, который выполнится один раз. Какая разница четыре там выделения памяти или ноль? Никто никогда не заметит этой разницы глазом.

Ответить | Правка | К родителю #123 | Наверх | Cообщить модератору

89. "Выпуск языка программирования Rust 1.33"  –1 +/
Сообщение от Аноним (41), 03-Мрт-19, 06:25 
> connect_headerbars (который вероятно был заинлайнен
> и поэтому

Не является причиной.

> не имеет самостоятельного стекового фрейма в release)

_Даже_если_ так, не играет роли (и стандарт не оперирует абстракциями "регистр rbp"). Изучай существующие имплементации обработчиков, если интересны детали.

Ответить | Правка | К родителю #70 | Наверх | Cообщить модератору

95. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 07:24 
Не понял. Не является причиной чему? Не играет роли какой? При чём тут имплементации обработчиков?

Ты хочешь этим намекнуть, что ты знаешь каким образом строится бектрейс, который выводится при RUST_BACKTRACE=1, и полагаешь, что если этот бектрейс не содержит в себе каких-то функций, которые по логике вещей должны были бы там быть, то это вовсе не потому, что эти функции были заинлайнены? Если ты так думаешь, то ты глубоко и печально ошибаешься. Сделай по сорцам раста find . -name libunwind, и загляни туда. Ты увидишь, что размотка стека на линуксе идёт посредством libgcc_s.so. Который -- сюрприз-сюрприз -- тоже входит в список абстракций, которым не оперирует стандарт. Подстава, да?

Ответить | Правка | Наверх | Cообщить модератору

115. "Выпуск языка программирования Rust 1.33"  –1 +/
Сообщение от Аноним (41), 03-Мрт-19, 14:40 
> Не понял. Не является причиной чему?

Упомянутым якобы ограничениям. По стековым фреймам в *nix см. red zone, кадры не всегда организуются даже когда нужны.

> Не играет роли какой?

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

> При чём
> тут имплементации обработчиков?

Стандарт С++ определяет семантику исключений и приходится соответствовать. То есть перевод разговора на уровень имплементации рантайма трактуются лишь в ключе "я (не) знаю как".

> Ты хочешь этим намекнуть, что ты знаешь каким образом строится бектрейс, который
> выводится при RUST_BACKTRACE=1

Скажу прямо: это не моя забота знать, как там в Rust и почему inline стало проблемой, когда в С++ таковой не является.

Ответить | Правка | Наверх | Cообщить модератору

119. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 03-Мрт-19, 15:06 
> По стековым фреймам в *nix см. red zone, кадры не всегда организуются даже когда нужны.

И что? Стековый фрейм начинается адресом возврата, и продолжается до следующего адреса возврата. То что ты называешь "организацией кадра" -- это лишь специальные телодвижения сводящиеся к тому, чтобы положить в известное и доступное место адрес этого самого стекового фрейма.

> Стандарт С++ определяет семантику исключений и приходится соответствовать. То есть перевод разговора на уровень имплементации рантайма трактуются лишь в ключе "я (не) знаю как".

Ах, так ты о C++ говоришь? И чё, бектрейсы в C++ пишут и про заинлайненные функции? Вот если я напишу C++ программу, скомпилирую её с -O2, стрипну всю дебаг-инфу из файла, то я смогу получить полный список вложенных вызовов в бектрейсе?

> Скажу прямо: это не моя забота знать, как там в Rust и почему inline стало проблемой, когда в С++ таковой не является.

Ты сам с собой разговариваешь? Где тут ты видишь проблему? Что бектрейс неполный? Дык это преимущество, это значит что бинарь не содержит всяких ненужностей, что inline-функция именно что inline функция, она встроена в вызывающую её функцию, будто она там была написана, она, в некоторых случаях, может быть оптимизирована так, что в коде не останется ни одной инструкции машинного кода от неё. Это преимущество, это хорошо и прельстиво. Если же тебе это не нравится, собирай debug-билд.

Ответить | Правка | Наверх | Cообщить модератору

125. "Выпуск языка программирования Rust 1.33"  –1 +/
Сообщение от Аноним (41), 03-Мрт-19, 18:09 
>> По стековым фреймам в *nix см. red zone, кадры не всегда организуются даже когда нужны.
> И что? Стековый фрейм начинается адресом возврата, и продолжается до следующего адреса
> возврата.

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

> То что ты называешь "организацией кадра" -- это лишь специальные
> телодвижения сводящиеся к тому, чтобы положить в известное и доступное место
> адрес этого самого стекового фрейма.

Организация кадра выполняется модификацией регистра процессора "указатель стека" (иногда используется регистр "базы стека"). Действительно, упомянутый регистр - известное место.

>> Стандарт С++ определяет семантику исключений и приходится соответствовать. То есть перевод разговора на уровень имплементации рантайма трактуются лишь в ключе "я (не) знаю как".
> Ах, так ты о C++ говоришь?

Ну да. Выше кто-то заявил, что в С++ с этим нет проблем.

> И чё, бектрейсы в C++ пишут
> и про заинлайненные функции? Вот если я напишу C++ программу, скомпилирую
> её с -O2, стрипну всю дебаг-инфу из файла, то я смогу
> получить полный список вложенных вызовов в бектрейсе?

Уверен, сможешь. Возможно, не с первой попытки, но сможешь. Ты специалист весьма грамотный и упорный, другое дело, что больше интересуешься высоким уровнем, а не всякими rop-гаджетами.

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

>> Скажу прямо: это не моя забота знать, как там в Rust и почему inline стало проблемой, когда в С++ таковой не является.
> Ты сам с собой разговариваешь? Где тут ты видишь проблему?

Я просто поверил тебе, как специалисту по Rust. Ты же сам сообщил, что из-за инлайна не будет стекового фрейма и потому в итоге вываливается паника, а иначе сделать нельзя.


Ответить | Правка | Наверх | Cообщить модератору

137. "Выпуск языка программирования Rust 1.33"  +/
Сообщение от Ordu (ok), 04-Мрт-19, 12:23 
> Адрес возврата это адрес возврата - его рисуют на картинках в книжках для пущего понимания и целостности картины. Эти данные не относятся к исключениям.

Что значит не относятся, если адреса возврата используются при размотке стека? То есть, возможны варианты организации размотки стека, когда ради неё создаётся отдельный стек, но... Не знаю как там в C++, думаю нет, и совершенно определённо этого не делается в rust'е. В стековом фрейме всё фигня, а адресами возврата устанавливается связь между вложенными контекстами выполнения. Ради этих адресов возврата стек и существует, всё остальное в стеке оказывается там по принципу: если уж у нас есть стек, то почему бы не использовать его под локальные переменные и под передачу аргументов в функции.

Весь мой опыт отладки говорит, что адрес возврата -- это самая удобная точка отсчёта границ между стековыми фреймами. Даже если под адресом возврата лежат аргументы функции, всё равно удобнее ориентироваться на адрес возврата, потому что он будет даже тогда, когда аргументы передаются в регистрах, или когда их переменное число. Более того, если ты хочешь сделать что-нибудь типа tail-call'а, или вернуться из функции при помощи iret, хотя вызывали твою функцию командой call, или ещё какой-нибудь такой трюк провернуть, то тебе будет глубоко наплевать где там на стеке лежит значение bp/ebp/rbp, тебя будет в первую очередь интересовать, где лежит адрес возврата.

> Организация кадра выполняется модификацией регистра процессора "указатель стека" (иногда используется регистр "базы стека"). Действительно, упомянутый регистр - известное место.

Спасибо за справку.

> Тут надо понимать, что дебажная инфа не относится к исключениям.

Относится... Не относится... Какая разница мне, если при отсутствии отладочной информации я не могу увидеть осмысленного бектрейса от вылетевшего исключения? А речь идёт ведь именно о бектрейсе вполне конкретного исключения (то есть паники) на вполне конкретном коде.

Из наблюдений за тобой, я сформировал полезный совет тебе. Ну, познание -- моя больная тема: то как человеческие мозги упорядочивают входящий поток информации, которую они получают от рецепторов -- это очень интересный вопрос. И глядя на тебя, я вижу что ты немного не так расставляешь акценты, занимаясь познанием реальности. Собственно следующая портянка как раз об этом. Если тебе это tl;dr, ты можешь скипнуть к следующей цитате себя и читать оттуда.

Не надо так упорно пытаться делить вещи на те, которые относятся к X и те которые не относятся к X, для любого X. Вселенная не работает так. То что ты пытаешься делать -- это очень удобный способ упорядочивать информацию о Вселенной в голове, но надо быть готовым к тому, что отношение между вещами и X окажется субъективным. То есть с одной стороны его нет, с другой стороны оно есть -- как посмотреть. Граница между X и не-X -- это всегда размытая граница, там всегда есть серая область, которая иногда относится к X, а иногда нет.

Скажем, все твои рассуждения о стековых фреймах, построены на каком-то определении стекового фрейма, в котором очевидно упоминался rbp. Из чего по логике вытекает, что если не используется rbp или его аналог, то стекового фрейма нет. Чёткая граница между X и не-X, где X -- множество стековых фреймов. Но если ты попытаешься, например, отревёрсить программу, которая не использует rbp, ты будешь ковырять эту программу в дизассемблере и отладчике, и ты всё равно будешь думать о стековых фреймах, даже несмотря на то, что доступ к переменным на стеке программа выполняет посредством адресации относительно rsp. И тебе будет совершенно не важно, что там вумные люди пишут во всяких вумных учебниках о том, что они считают стековым фреймом. Даже более того, в качестве исторической справки, я скажу тебе, что использование bp, ebp и rbp для организации стека, возникло исходно лишь потому, что в 16-битном режиме интеловские процессоры не умеют в косвенную адресацию через sp, там все эти SIB да MOD/rm байты в системе команд кодируются так, что через sp никак. В 32-битном коде SIB и modrm декодируются несколько иначе, и они позволяют использовать esp, но... но люди продолжали использовать bp по двум причинам: во-первых, привычка, во-вторых, без фиксированной ссылки на стековый фрейм в ebp было невозможно пользоваться дебуггером высокоуровневого языка. Надо либо кодировать на каждую строчку кода смещение esp от адреса возврата на момент выполнения этой строчки кода (компилятор так или иначе отслеживает эту инфу, он её использует, но не сохраняет в бинаре), либо учить дебуггер всяким хитрым трюкам, чтобы тот анализируя выполняемые команды сам бы высчитывал все эти смещения. То есть, когда код стал 32-битным (и тем более 64-битным), использование ebp/rbp для организации стекового фрейма стало лишь данью тупости отладчиков, такой же данью тупости отладчиков, как и отладочная инфа. Ещё его можно использовать для размотки стека в случае исключений, но можно и не использовать, придумав какой-нибудь иной способ. А, если мы, разматывая стек, хотим ещё и ресурсы подбирать и освобождать, то что-то иное всё равно приходится придумывать, и это что-то иное может не включать в себя использование rbp для организации стекового фрейма. Но так или иначе, ты видишь, да? Граница между X и не-X размазалась, и уже неясно, нужен ли rbp для организации стекового фрейма, или это просто дань традиции, возникшей из-за убогости первых x86.

То же самое происходит и с отладочной информацией. Она нужна для отладки. Точка. Чёткая граница между X и не-X, где X -- это инфа для отладки. Но... эмм... если мы всунем обрезанный вариант этой отладочной инфы в релиз, то мы сможем получать осмысленные бектрейсы, которые могут помочь нам общаться с пользователями о багах. Обрезанный вариант -- это без номеров строк, без информации о размещении переменных на стеке, без всего, лишь информацию о границах функций в секции кода, и каноничные имена этих функций, со ссылками на файлы где они объявлены. То есть, это тоже, как бы, "для отладки", но в то же время, как бы, и не совсем для отладки.

Отладочная информация может использоваться и для того, чтобы определить факт того, что исключение возникло не в функции foo, а в функции bar, которая была заинлайнена в foo. Я не знаю, используется ли она в действительности всякими разными библиотеками, которые позволяют программе построить свой бектрейс. То есть, де факто, отладочная информация используется ими -- иначе бы бектрейсы программы с отладочной инфой не отличались бы от бектрейсов программ без неё. Но тут вопрос в том, может ли построитель бектрейса в C++ использовать эту информацию для определения того, что на стековом фрейме foo сверху есть ещё стековый фрейм функции bar, несмотря на то, что bar не вызывался через call, и адрес возврата не клался на стек, и вообще после того как bar был заинлайнен, при взгляде на дизассемблерный дамп даже возникает сомнение в осмысленности разговора о том, что какой-то кусок foo -- это на самом деле самостоятельная функция bar.

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

Отладочная инфа или не *отладочная* инфа -- вот в чём вопрос, границы опять расплываются. Относится "отладочная" инфа к размотке стека или не относится? Не надо излишне парится о чёткости этих границ, чёткость должна быть на экзамене, потому что экзамены часто принимаются тупыми педантами. Чёткость может оказаться полезной при общении с другим человеком, но тут палка о двух концах: если твои чёткие границы между понятиями будут пролегать немного не там, где его чёткие границы между понятиями, то вам будет очень сложно понять друг-друга, более того вы будете рисковать не понять того, что вы не понимаете друг-друга, а это худшее, что может случиться в коммуникации. Даже мордобой, как способ вести коммуникацию, не столь плох, потому что он по-крайней мере несёт в себе чёткое взаимопонимание хотя бы по одному вопросу.

> Уверен, сможешь. Возможно, не с первой попытки, но сможешь. Ты специалист весьма грамотный и упорный, другое дело, что больше интересуешься высоким уровнем, а не всякими rop-гаджетами.

Это "да" или "нет"? Я знаю, что я смогу, мне в жизни удавалось заставлять работать очень странные вещи и очень странными способами. Но это не ответ на поставленный вопрос.

Впрочем, я уже догадался, что ответ -- нет. Если бы ответ был "да", ты бы не извивался тут ужом на сковородке, пытаясь изобразить что-то похожее на ответ так, чтобы оно не содержало бы в себе актуального ответа.

> Ты же сам сообщил, что из-за инлайна не будет стекового фрейма и потому в итоге вываливается паника, а иначе сделать нельзя.

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

Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру