Pro ty co odmitaji akceptovat, ze ne-programatora zachrani lepsi, nekdy az magicke nastroje hodne nekonecne adorace (jako Rust), zde mate priklad (inspirovany realnou situaci, kterou jsem videl u kamarada programatora).
#include <stdio.h>
#include <stdint.h>
void recursion(uint32_t level) {
if ((level%1000)==0) {
printf("level = %d\n",level);
}
if (level==1000000000) {
return;
}
recursion(level+1);
}
int main( int argc, char* argv[] ) {
recursion(0);
return 0;
}
vs:
fn recursion( level: u32 ) {
if (level%1000) == 0 {
println!("level = {}",level);
}
if level == 1000000000 {
return;
}
recursion(level+1);
}
fn main() {
recursion(0);
}
A vysledek:
$ gcc recursion.c -o recursion $ ./recursion ... level = 260000 level = 261000 Segmentation fault
$ rustc recursion.rs $ ./recursion ... level = 103000 level = 104000 thread 'main' has overflowed its stack fatal runtime error: stack overflow Aborted
Oba kody se prelozi bez varovani prekladace, oba kody padnou.
Sebelepsi nastroj vas nezachrani, kdyz neumite programovat.
A ten v Rust-u padne drive, protoze pracuje evidentne mene optimalne se zasobnikem pri volani funkci. Nerikal nekdo ze Rust je lepsi? Aha.. tak asi ne jako.
Velikost vysledne binarky bych radeji nekomentoval - ale 14.7K vs 4225K taky nelze prehlidnout (ale o tom tento priklad neni).
Pro ty co odmitaji akceptovat, ze ne-programatora zachrani lepsi, nekdy az magicke nastroje hodne nekonecne adorace
Slovo „zachrání“ jste tu použil jediný vy, nikdo jiný. Slovo „magické“ jste použil vy, nikdo jiný. Nekonečnou adoraci tu také nikdo nepředvádí.
Oba kody se prelozi bez varovani prekladace, oba kody padnou.
Oba překladače nikdy netvrdily, že dokážou zabránit problémům tohoto typu.
Sebelepsi nastroj vas nezachrani, kdyz neumite programovat.
Polemizujete s něčím, co nikdo netvrdil.
Nerikal nekdo ze Rust je lepsi? Aha.. tak asi ne jako.
Nikdo neříkal, že je ve všem lepší.
Velikost vysledne binarky bych radeji nekomentoval
Možná byste se měl podívat do kalendáře, jaký je rok. 4 MB binárky na PC fakt není něco, co by někoho trápilo.
Viz pocet cyklu pred padem.
Predpokladam ze zasobnik je stejne veliky by default a ani jeden program bez meho svoleni nesaha na zmenu ulimit.
Lisit se to muze samozrejme zaplnenosti tim, co se tam nahaze pred spustenim main().
Pak uz jenom nastava rekurzivni volani a na zasobnik se ukladaji (nekdy) argumenty a navratova adresa. Mozna tam Rust uklada i neco dalsiho, o cem nevime ze potrebujeme/chceme ale je to tam?
Jaky je tedy calling convention v rustu? (obecne neni definovany, a zde byla platforma 32bit x86 linux)
EDIT: na druhe pomysleni me napada ze je mozna situace, ze GCC ten argument prenasi v registru, a RUSTC ho uklada vzdy na zasobnik?
4. 11. 2023, 17:48 editováno autorem komentáře
Fascinující, stack overflow dovede potkat jakýkoliv jazyk co pracuje se stackem. Jen to vede k pádu aplikace, ne ke spuštění arbitrary kódu, nebo exfiltraci dat z paměti. A prostě ignorujme x chyb kterým jazyk předejde, tady je jedna kterou nevyřeší :)
Velikost binárky je dost stupidní argument btw. Ok, možná se věc velikosti "hello world" liší, ale chce to spíš porovnat reálnou aplikaci co něco dělá, velikost runtime hned ztratí význam proti zbytku kódu.
Jaky runtime probuh??
Nemel by vystup rustc byt nativni strojovy kod, je to prece kompilovany jazyk!
Aby si clovek vytracoval instrukce a cestu kterou to provede skrze ty megabajty.. rekl bych ze se z toho neprovede o moc vice, nez u bezneho C hello world. Proste neni zadny duvod tam poustet neco dalsiho a je to jen neoptimalni balast.
ono i to cecko do toho Hello world dava nesmysly. Nejaky puts je jedno volani jadra, exit/return je druhe volani jadra. Dohromady je to na par bajtu, trosku to naroste kvuli strukture binarky (uz ne a.out ale vetsi ELF), ale porad to jsou max. kilobajty. Ale ceckovej runtime do toho dava veci okolo libc, startup kod atd. A Rust - to je trosku zahada, co tam vsechno je (musi byt?).
Úplně stejný jako má třeba C++ https://stackoverflow.com/a/1824550
https://www.quora.com/What-is-the-C++-runtime-system-and-how-does-it-work?top_ans=20541236
Hele, fakt by to chtělo nejdřív znát základy a pak kritizovat jazyky :)
Většina z velikosti Rust binárky je debug info, které lze snadno stripnout. Přidej do Cargo.toml:
[profile.release] strip = true lto = true
a dostaneš:
$ cargo build --release $ ls -lh target/release/recursion 339K target/release/recursion
Jde to ještě víc zmenšit, ale nikoho to na AMD64 architekruře nezajímá, tohle není reálný problém.
no_sdt je už docela hardcore. Jednodušší je rebuildovat std pomocí build-std: https://github.com/johnthagen/min-sized-rust#optimize-libstd-with-build-std