#prog #rust
Одним из пунктов снижения размера исполняемого файла скомпилированной программы на Rust является обработка бинаря strip. Недавно это стало возможным делать с помощью cargo. Да, это пока nightly, но это значит, что, скорее всего, на stable попадёт скоро.
(thanks @MikailBag)
Одним из пунктов снижения размера исполняемого файла скомпилированной программы на Rust является обработка бинаря strip. Недавно это стало возможным делать с помощью cargo. Да, это пока nightly, но это значит, что, скорее всего, на stable попадёт скоро.
(thanks @MikailBag)
GitHub
Add option to strip binaries by GabrielMajeri · Pull Request #8246 · rust-lang/cargo
This PR adds a Cargo option for stripping symbols from generated binaries.
This is based on the -Z strip flag for rustc, which has been recently implemented.
Notes for reviewers: I'm not entire...
This is based on the -Z strip flag for rustc, which has been recently implemented.
Notes for reviewers: I'm not entire...
#prog #rust #go #article
Во многих языках есть отдельный тип данных для символов (я смотрю на тебя, Python). В Rust это
christianfscott.com/rust-chars-vs-go-runes
Во многих языках есть отдельный тип данных для символов (я смотрю на тебя, Python). В Rust это
char
, в Go это rune
. Эти типы, казалось бы, одинаковы: оба хранят юникодные символы, оба занимают 32 бита. Тем не менее, в плане диапазона приемлемых значений они заметно отличаются. Чем именно — подробно рассказывается в статье.christianfscott.com/rust-chars-vs-go-runes
Закон Каннингема: лучший способ найти ответ на интересующий тебя вопрос в Интернете — это выложить не сам вопрос, а неправильный ответ на него.
Что интересно, сам Уорд Каннингем авторство этого закона отвергает.
Что интересно, сам Уорд Каннингем авторство этого закона отвергает.
Wikipedia
Ward Cunningham
American computer programmer who developed the first wiki
Знаете, что меня раздражает? Люди, которые делают посты с хэштегом #mood и какой-то прикреплённой музыкой. Ну вот что эти люди хотят этим сказать?
Показать, какой сейчас у них настроение? А не проще ли сказать это, блин, словами?
Показать, что они сейчас слушают? Ну, для этого есть статусы, где можно указать трек или, на худой конец, его название.
Сделать пост ради поста? Да ради, сука, бога, только нахрена туда вставлять хэштег, который переводится как "настроение"? Они хоть вообще знают, что хэштеги несут семантическую нагрузку?
А ведь трек бывает и не один. На что эти люди надеются? На то, что кто-то потратит несколько минут своей жизни на то, чтобы оценить их выбор музыки? На то, чтобы оценить их офигенно богатый внутренний мир? Да нет же, френды просто максимум лайк поставят и будут листать ленту дальше, слушая свою, чёрт побери, музыку.
Абсолютно бессмысленная вещь. Бесит, аж горит.
#бомбёжкипост
Показать, какой сейчас у них настроение? А не проще ли сказать это, блин, словами?
Показать, что они сейчас слушают? Ну, для этого есть статусы, где можно указать трек или, на худой конец, его название.
Сделать пост ради поста? Да ради, сука, бога, только нахрена туда вставлять хэштег, который переводится как "настроение"? Они хоть вообще знают, что хэштеги несут семантическую нагрузку?
А ведь трек бывает и не один. На что эти люди надеются? На то, что кто-то потратит несколько минут своей жизни на то, чтобы оценить их выбор музыки? На то, чтобы оценить их офигенно богатый внутренний мир? Да нет же, френды просто максимум лайк поставят и будут листать ленту дальше, слушая свою, чёрт побери, музыку.
Абсолютно бессмысленная вещь. Бесит, аж горит.
#бомбёжкипост
#prog #rust #article
Обстоятельное эмпирическое изучение ошибок в реальных программах на Rust. Деление на safe/unsafe код действительно помогает, но все баги с излишней блокировкой были найдены в safe коде. Особенности Rust делают некоторые паттерны ошибок более вероятными, чем в других языках. Изучение этих паттернов позволило создать статические анализаторы, которые вскрыли ранее незамеченные ошибки.
Читайте, когда найдётся свободное время, статья объёмная.
cseweb.ucsd.edu/~yiying/RustStudy-PLDI20.pdf
Обстоятельное эмпирическое изучение ошибок в реальных программах на Rust. Деление на safe/unsafe код действительно помогает, но все баги с излишней блокировкой были найдены в safe коде. Особенности Rust делают некоторые паттерны ошибок более вероятными, чем в других языках. Изучение этих паттернов позволило создать статические анализаторы, которые вскрыли ранее незамеченные ошибки.
Читайте, когда найдётся свободное время, статья объёмная.
cseweb.ucsd.edu/~yiying/RustStudy-PLDI20.pdf
#prog #cpp
Для C++ существует такая вещь, как CppCoreGuidelines. Это набор рекомендаций и лучших практик, нацеленных на то, чтобы люди более эффективно (читай, менее ногострельно) использовали C++. Частью этих гайдлайнов является разработанный Гербом Саттером документ, описывающий формализацию времён жизни в C++ и позволяющий отлавливать использование висячих ссылок. Разумеется, от такого документа мало толку, если всё это проверять вручную, но есть lifetime profiler — форк clang, в котором реализован статический анализатор, работающий согласно документу выше. Его можно сбилдить самостоятельно и использовать локальнотолько зачем, а можно открыть godbolt.org и использовать компилятор
Начну немного издалека. В стандартной библиотеке C++ есть тип string (аналог в Rust — String). Это изменяемая строка из символов в неопределённой кодировке, хранящая данные в куче (как правило, ибо стандарт не запрещает использовать small string optimisation, когда маленькие строки хранятся на стеке, а не в куче). Самое главное — это владеющий тип: когда значение типа std::string выходит из области видимости, память, выделенная под данные строки, удаляется. В отличие от Rust, этот тип является неявно копируемым (что логично, учитывая, что этот тип появился сильно раньше move semantics): когда std::string передаётся аргументом в функцию, в куче выделяется память под копию строки и в неё копируются данные этой строки. Это может заметно снизить производительность. Для того, чтобы избежать ненужных аллокаций, стоит передавать строку по ссылке.
Так что же, есть производительный способ работать со строками без лишних трат? Не совсем. У std::string есть метод substr, который возвращает подстроку с указанных позиций, но проблема в том, что этот метод возвращает std::string, то есть выделяет память в куче. Как-то не зирокост. Можно, конечно, передавать ссылку на строку и индексы, выделяющие подстроку, но это неудобно. Для решения этой проблемы в разных библиотеках — в том числе, в boost — делали свои собственные типы. Они являлись невладеющими строками и хранили в себе лишь ссылку на данные исходной строки и позицию подстроки. Они дёшево копируются, и выделить подстроку при помощи такого типа также очень дёшево: достаточно поменять пару индексов. В стандарте C++17 подобный тип наконец-то добавили в стандартную библиотеку — это string_view, определённый в заголовочном файле
Так что, теперь всё хорошокак будто в C++ в принципе что-то может быть хорошо? К сожалению, нет. Так как string_view является семантически невладеющим указателем, он, как и любой невладеющий указатель, может стать висячим (dangling). Получить висячий string_view в C++ довольно просто, особенно если учесть, что string_view неявно конвертируется из string. Более того, присваивание ссылке может продлить время жизни временного объекта, но с string_view это не работает, потому что они не являются ссылками, поэтому можно в одно строке создать временную строку, присвоить её переменной типа string_view... И получить невалидный string_view, поскольку временная строка будет уничтожена в конце строки. Что ж, звучит как проблема, которую может отловить анализатор времён жизни!
Для начала напишем пару функций, оперирующих string_view:
Для C++ существует такая вещь, как CppCoreGuidelines. Это набор рекомендаций и лучших практик, нацеленных на то, чтобы люди более эффективно (читай, менее ногострельно) использовали C++. Частью этих гайдлайнов является разработанный Гербом Саттером документ, описывающий формализацию времён жизни в C++ и позволяющий отлавливать использование висячих ссылок. Разумеется, от такого документа мало толку, если всё это проверять вручную, но есть lifetime profiler — форк clang, в котором реализован статический анализатор, работающий согласно документу выше. Его можно сбилдить самостоятельно и использовать локально
x86-64 clang (experimental -Wlifetime)
. Как же этот анализатор работает на практике?Начну немного издалека. В стандартной библиотеке C++ есть тип string (аналог в Rust — String). Это изменяемая строка из символов в неопределённой кодировке, хранящая данные в куче (как правило, ибо стандарт не запрещает использовать small string optimisation, когда маленькие строки хранятся на стеке, а не в куче). Самое главное — это владеющий тип: когда значение типа std::string выходит из области видимости, память, выделенная под данные строки, удаляется. В отличие от Rust, этот тип является неявно копируемым (что логично, учитывая, что этот тип появился сильно раньше move semantics): когда std::string передаётся аргументом в функцию, в куче выделяется память под копию строки и в неё копируются данные этой строки. Это может заметно снизить производительность. Для того, чтобы избежать ненужных аллокаций, стоит передавать строку по ссылке.
Так что же, есть производительный способ работать со строками без лишних трат? Не совсем. У std::string есть метод substr, который возвращает подстроку с указанных позиций, но проблема в том, что этот метод возвращает std::string, то есть выделяет память в куче. Как-то не зирокост. Можно, конечно, передавать ссылку на строку и индексы, выделяющие подстроку, но это неудобно. Для решения этой проблемы в разных библиотеках — в том числе, в boost — делали свои собственные типы. Они являлись невладеющими строками и хранили в себе лишь ссылку на данные исходной строки и позицию подстроки. Они дёшево копируются, и выделить подстроку при помощи такого типа также очень дёшево: достаточно поменять пару индексов. В стандарте C++17 подобный тип наконец-то добавили в стандартную библиотеку — это string_view, определённый в заголовочном файле
<string_view>
. Аналогом этого типа в Rust выступает &str
.Так что, теперь всё хорошо
Для начала напишем пару функций, оперирующих string_view:
#include <string>
#include <string_view>
using sv = std::string_view;
sv shortest(sv a, sv b) {
return a.size() < b.size() ? a : b;
}
sv cut_prefix(sv prefix, sv str) {
//
не спрашивайте if (str.rfind(prefix, 0) == 0) {
return str.substr(prefix.size());
} else {
return str;
}
}
Эти функции имеют одинаковые сигнатуры, но между ними есть большое отличие: shortest может вернуть любой из двух аргументов, а вот cut_prefix может вернуть только второй аргумент или подстроку из него.Что ж, попробуем использовать
...Если посмотреть README к форку, можно увидеть ещё один флаг,
Ну, ладно, это я испорчен растом, на самом деле тот факт, что компилятор C++ ловит подобные ошибки безо всяких аннотаций со стороны пользователя, пусть и с ложноположительными результатами — это довольно круто. Но что, если мы захотим передавать функцию отдельным параметром? Давайте проверим:
Ну, хорошо, хорошо, это шаблоны, их действительно сложно анализировать, из-за них парсинг C++ является полной по Тьюрингу задачей. Давайте сделаем что-нибудь попроще, скажем, то, что было ещё в C: указатели на функции:
Заключения не будет.
-Wlifetime
на практике:sv example_should_err(int n, sv str) {На первый пример компилятор выдаёт предупреждение:
auto n_str = std::to_string(n);
return shortest(n_str, str);
}
sv example_should_ok(int n, sv str) {
auto n_str = std::to_string(n);
return cut_prefix(n_str, str);
}
<source>:20:5: warning: returning a dangling pointer [-Wlifetime]И совершенно правильно, потому что тут может быть возвращён string_view, созданный из временной строки, которая уничтожается на выходе из функции. Что же касается второго примера... Тоже предупреждение. Причём то же самое :/ Хотя тут string_view от n_str заведомо не покидает пределы функции.
return shortest(n_str, str);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:20:5: note: pointee 'n_str' left the scope here
return shortest(n_str, str);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
...Если посмотреть README к форку, можно увидеть ещё один флаг,
-Wlifetime-filter
. Цитирую: "Reduce the number of false-postives at the cost of additional false negatives.". Добавляем этот флаг и... Получаем тот же самый выхлоп.Ну, ладно, это я испорчен растом, на самом деле тот факт, что компилятор C++ ловит подобные ошибки безо всяких аннотаций со стороны пользователя, пусть и с ложноположительными результатами — это довольно круто. Но что, если мы захотим передавать функцию отдельным параметром? Давайте проверим:
template <typename F> sv example_hof(int n, sv str, F func) {Кладём в компилятор и... Получаем ноль предупреждений.
auto n_str = std::to_string(n);
return func(n_str, str);
}
sv example_hof_should_ok(int n, sv str) {
return example_hof(n, str, cut_prefix);
}
sv example_hof_should_err(int n, sv str) {
return example_hof(n, str, shortest);
}
Ну, хорошо, хорошо, это шаблоны, их действительно сложно анализировать, из-за них парсинг C++ является полной по Тьюрингу задачей. Давайте сделаем что-нибудь попроще, скажем, то, что было ещё в C: указатели на функции:
sv example_hof(int n, sv str, sv (*func)(sv, sv)) {Проверяем... Ноль предупреждений.
auto n_str = std::to_string(n);
return func(n_str, str);
}
// example_hof_should_ok и example_hof_should_err остались без изменений
Заключения не будет.
godbolt.org
Compiler Explorer - C++ (x86-64 clang (experimental -Wlifetime))
using sv = std::string_view;
sv shortest(sv a, sv b) {
return a.size() < b.size() ? a : b;
}
sv cut_prefix(sv prefix, sv str) {
if (str.rfind(prefix, 0) == 0) {
return str.substr(prefix.size());
} else {
return str;
}
}
…
sv shortest(sv a, sv b) {
return a.size() < b.size() ? a : b;
}
sv cut_prefix(sv prefix, sv str) {
if (str.rfind(prefix, 0) == 0) {
return str.substr(prefix.size());
} else {
return str;
}
}
…
Forwarded from мне не нравится реальность (вафель 🧇)
Улучшал код
Силой святой копипасты у меня получилось деление на 0 😅
typed_phy
и случайно наткнулся на такое прекрасное...Силой святой копипасты у меня получилось деление на 0 😅
#prog #article
Как сделать из notepad.exe экран для рендера трёхмерных изображений с FPS 30.
kylehalladay.com/blog/2020/05/20/Rendering-With-Notepad.html
Как сделать из notepad.exe экран для рендера трёхмерных изображений с FPS 30.
kylehalladay.com/blog/2020/05/20/Rendering-With-Notepad.html
Kylehalladay
Kyle Halladay - Ray Tracing In Notepad.exe At 30 FPS
I build shaders, renderers, games, and other stuff that's fun to stare at.
#prog #cpp
В C++ в наследство от C достались операторы инкремента и декремента (
Если это не костыль, то я даже не знаю, как это назвать.
stackoverflow.com/questions/15244094/c-overloading-for-both-pre-and-post-increment
В C++ в наследство от C достались операторы инкремента и декремента (
++
и --
). Как и любые операторы, их можно перегружать для своих типов. Но есть один нюанс: как различать префиксный и постфиксный инкременты? В C++ решение таково: префиксный оператор не принимает аргументов, а постфиксный принимает неиспользуемый параметр типа int.Если это не костыль, то я даже не знаю, как это назвать.
stackoverflow.com/questions/15244094/c-overloading-for-both-pre-and-post-increment
Stack Overflow
C++: overloading ++ for both pre and post increment
Can we overload operator++ for pre-increment and post-increment? i.e. calling SampleObject++ and ++SampleObject results correctly.
class CSample {
public:
int m_iValue; // just to directly
class CSample {
public:
int m_iValue; // just to directly