20-talets högsta prioritet på språk - Säkerhet & Snabbhet

Permalänk

20-talets högsta prioritet på språk - Säkerhet & Snabbhet

Jag har forskat lite bland språk då jag har kommit i kontakt med "C++ vs Rust" debatter dom senaste månaderna och sett lite statistik om vilka språk som är snabbast.

Jag brukar följa Dave's Garage på YouTube: https://www.youtube.com/watch?v=pSvSXBorw4A&ab_channel=Dave%2...

Han listar 5 snabbaste språken idag:

  1. Zig

  2. Rust

  3. C

  4. C++

  5. Java

Han beskriver deras styrkor och syften. Han går inte in på deras nackdelar, då det är inte relevant. Men något som jag märker att han pratar mycket om är just säkerhet kring dessa språk. Java ska tydligen vara supersäkert att programmera i. C och C++ är inte alls säkra språk. Rust är mycket säkert. Jag kan inte uttala mig hur säkert Rust är, men jag har läst att Rust skapades för att vara säkert.

Men sedan finns det ett språk till som, enligt Dave's Garage, är det snabbaste språket. Det är Zig. Zig är tydligen en "kopia" på C++ fast med en säkerhet som Java och en snabbhet som C.

Jag började gräva djupare bland Zig och helt plötsligt så hittade jag "Zig VS Rust" debatter där Zig anses vara ett bättre språk.
Jag grävde ännu djupare och nu hittar jag "Carbon Vs Zig".

Det allt detta "VS" handlar om är just minnessäkerhet och snabbhet. Bara det. Inget annat.
Då tänkte jag, är inte detta just 20-talets framtida fokus på språk?

På 90-talet så skulle OOP vara högst prioriterat. Allt skulle vara en klass. på 00-talet så skulle allt kunna köras överallt, typ Python, Java, Matlab, C# osv. På 10-talet så skulle allt optimeras och nu så är säkerhet största fokus.

Vad tror ni? Kommer vi se ett språk som är så fasansfullt säkert att man knappt behöver skriva kod?

Övrigt så tycker jag Zig ser lovande ut. En relativ enklare syntax som är lätt att läsa, jämfört med Rust. Men jag vågar nog inte investera min tid varken i Zig eller Rust för att snart har vi säkerligen ett nytt språk som konkurrerar ut allt och alla...Vem vet?

Kommer vi se nya språk(inom kort) som är ännu säkrare och snabbare än Zig? Om svaret är Ja: Varför gör man inte ett språk som är så optimerat att det går inte optimera något mera?

Permalänk
Medlem

Hur orkar du diskutera detta överallt, oavsett vilken tråd du vänder dig till?

Får jag fråga varför du bryr dig så mycket? Vill du lära dig det "snabbaste" språket och isåfall till vilket syfte?
I dagens läge är datorer extremt mycket mer kraftfulla jämfört med förr, det är vid extremt få tillfällen man i yrkeslivet väljer det "snabbaste" dvs mest effektiva språket.

Man väljer snarare det språket som är mest lämpat för den specifika uppgiften, oftast inte ett av de "snabbaste språken".

Bli en duktig utvecklare så behöver du inte lägga ned tid på att lära dig språk bara för att. Med tiden lär man sig lite olika paradigm och vips - när behovet uppstår att lära sig ett nytt språk så går det väldigt fort.

Visa signatur

10700K | NVIDIA RTX 3080

Permalänk
Skrivet av kwame:

Hur orkar du diskutera detta överallt, oavsett vilken tråd du vänder dig till?

Får jag fråga varför du bryr dig så mycket? Vill du lära dig det "snabbaste" språket och isåfall till vilket syfte?
I dagens läge är datorer extremt mycket mer kraftfulla jämfört med förr, det är vid extremt få tillfällen man i yrkeslivet väljer det "snabbaste" dvs mest effektiva språket.

Man väljer snarare det språket som är mest lämpat för den specifika uppgiften, oftast inte ett av de "snabbaste språken".

Bli en duktig utvecklare så behöver du inte lägga ned tid på att lära dig språk bara för att. Med tiden lär man sig lite olika paradigm och vips - när behovet uppstår att lära sig ett nytt språk så går det väldigt fort.

Föreställ dig att om ingen ställde dessa frågor, så skulle det inte skett någon utveckling.
Det är nyfikenheten som gör våra val.

För mig är ett språk inte bara ett verktyg, det är en dyr investering.

Permalänk
Hedersmedlem
Skrivet av heretic16:

Föreställ dig att om ingen ställde dessa frågor, så skulle det inte skett någon utveckling.
Det är nyfikenheten som gör våra val.

För mig är ett språk inte bara ett verktyg, det är en dyr investering.

Att lära sig programmeringspråk (som hobby) är ju gratis.
Jag har programmerat i alla de där utom Zig, och en bra massa utöver dem, allt på hobbynivå. Ser ingen god anledning att bli expert på ett enda språk när inget språk kan göra allting bra -- jag kör olika språk till småprogram med GUI (kanske Python med Qt), små enkla script (Bash, Perl, Python), Android-appar (Kotlin, Java), program där prestanda är kritiskt (C++, Rust) osv.
Är inte expert på något, men jag söker inte jobb som t ex C++-programmerare heller -- och även om jag skulle det så skulle det kännas värt det att kunna åtminstone en tre-fyra språk sådär.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

Permalänk
Medlem

Funderar lite såhär: Alla språk har ju loopar, if-satser, arrayer etc. (allt som gör ett program). Varför går det då inte att stärka t.ex. C-kompilatorn att implementera all den säkerhet som Rust har? Samma språk, men en ny kompilator-standard (eller helt ny kompilator) bara? Detta borde ju bevara know-how bättre hos den stora massan av programmerare än att ändra curley-brackets till indenteringar och allt som uppfinns i syntax-väg bara för att särskilja sig. (Minns tiden då alla lärde sig Pascal på högskolorna; bara för att kastas in i C-varianterna när de kom ut i arbetslivet.)

Permalänk
Medlem
Skrivet av mc68000:

Funderar lite såhär: Alla språk har ju loopar, if-satser, arrayer etc. (allt som gör ett program). Varför går det då inte att stärka t.ex. C-kompilatorn att implementera all den säkerhet som Rust har? Samma språk, men en ny kompilator-standard (eller helt ny kompilator) bara? Detta borde ju bevara know-how bättre hos den stora massan av programmerare än att ändra curley-brackets till indenteringar och allt som uppfinns i syntax-väg bara för att särskilja sig. (Minns tiden då alla lärde sig Pascal på högskolorna; bara för att kastas in i C-varianterna när de kom ut i arbetslivet.)

För att göra C säkert skulle du behöva ändra språket så mycket att det inte längre skulle vara C. Mängder av existerande kod skulle bli ogiltig.
Det räcker inte att bara förbättra kompilatorn - om det vore så enkelt så garanterar jag att det redan skulle gjorts.

Permalänk
Skrivet av mc68000:

Funderar lite såhär: Alla språk har ju loopar, if-satser, arrayer etc. (allt som gör ett program). Varför går det då inte att stärka t.ex. C-kompilatorn att implementera all den säkerhet som Rust har? Samma språk, men en ny kompilator-standard (eller helt ny kompilator) bara? Detta borde ju bevara know-how bättre hos den stora massan av programmerare än att ändra curley-brackets till indenteringar och allt som uppfinns i syntax-väg bara för att särskilja sig. (Minns tiden då alla lärde sig Pascal på högskolorna; bara för att kastas in i C-varianterna när de kom ut i arbetslivet.)

Jag har också tänkt samma banor. Varför kan inte t.ex en C-kompilator granska koden och säga "Nu blev det fel på rad 20"? Ska det vara så svårt år 2023?

Permalänk
Skrivet av Erik_T:

För att göra C säkert skulle du behöva ändra språket så mycket att det inte längre skulle vara C. Mängder av existerande kod skulle bli ogiltig.
Det räcker inte att bara förbättra kompilatorn - om det vore så enkelt så garanterar jag att det redan skulle gjorts.

Varför skulle den bli ogiltig? Jag har inte förstått detta. Så länge man inte rör syntaxen så anser jag att koden är helt enkelt orörd. Det är bara kompilatorn som har blivit smartare.

Permalänk
Medlem
Skrivet av heretic16:

Föreställ dig att om ingen ställde dessa frågor, så skulle det inte skett någon utveckling.
Det är nyfikenheten som gör våra val.

För mig är ett språk inte bara ett verktyg, det är en dyr investering.

Vilket språk som är "snabbast" är för det mesta inte bara ointressant, utan även omöjligt att fastslå med någon större säkerhet.
Hur snabbt ett program skrivet i ett visst språk blir beror väldigt mycket på hur bra kompilatorn är. Det beror också på vilka delar av språket som används.

För det allra mesta är vilka algoritmer man använder, hur man strukturerar sitt program, och hur man strukturerar sin data betydligt viktigare än vilket språk man använder.

För den stora merparten program så är "tillräckligt snabbt" alldeles tillräckligt. De behöver inte vara super-optimerade för att göra sitt jobb. Mycket, mycket viktigare är att de är lätta att förstå och modifiera, och naturligtvis att de inte innehåller fel.

För övrigt vill jag hävda, utan att ha några egentliga bevis för min tes, att Fortran är det snabbaste programmeringsspråket. Det är trots allt gjort för att vara bra på högprestandaberäkningar.
Motbevisa mig gärna.

Permalänk
Medlem
Skrivet av heretic16:

Varför skulle den bli ogiltig? Jag har inte förstått detta. Så länge man inte rör syntaxen så anser jag att koden är helt enkelt orörd. Det är bara kompilatorn som har blivit smartare.

Syntaxen är bara en bit. Semantiken är viktigare.
Och delar av semantiken i ett C program gör att kompilatorer inte kan upptäcka alla instanser av vissa typer av buggar.

Men som jag sade i en tidigare diskussion om det här - om du tror att det är enkelt att bara göra en C kompilator smartare så att C blir lika säkert som Rust, så tycker jag att du skall försöka göra de ändringarna själv. Om inte annat så kommer du att lära dig mycket om hur kompilatorer fungerar.
Och skulle du trots allt lyckas, på något mirakulöst sätt, så skulle mängder av C programmerare bli överlyckliga.

Permalänk
Skrivet av Erik_T:

Vilket språk som är "snabbast" är för det mesta inte bara ointressant, utan även omöjligt att fastslå med någon större säkerhet.
Hur snabbt ett program skrivet i ett visst språk blir beror väldigt mycket på hur bra kompilatorn är. Det beror också på vilka delar av språket som används.

För det allra mesta är vilka algoritmer man använder, hur man strukturerar sitt program, och hur man strukturerar sin data betydligt viktigare än vilket språk man använder.

För den stora merparten program så är "tillräckligt snabbt" alldeles tillräckligt. De behöver inte vara super-optimerade för att göra sitt jobb. Mycket, mycket viktigare är att de är lätta att förstå och modifiera, och naturligtvis att de inte innehåller fel.

För övrigt vill jag hävda, utan att ha några egentliga bevis för min tes, att Fortran är det snabbaste programmeringsspråket. Det är trots allt gjort för att vara bra på högprestandaberäkningar.
Motbevisa mig gärna.

Fortran är säkert mycket snabbt. Varför vet jag inte. Men jag ser dock ingen användning utav Fortran alls.

Permalänk
Skrivet av Erik_T:

Syntaxen är bara en bit. Semantiken är viktigare.
Och delar av semantiken i ett C program gör att kompilatorer inte kan upptäcka alla instanser av vissa typer av buggar.

Men som jag sade i en tidigare diskussion om det här - om du tror att det är enkelt att bara göra en C kompilator smartare så att C blir lika säkert som Rust, så tycker jag att du skall försöka göra de ändringarna själv. Om inte annat så kommer du att lära dig mycket om hur kompilatorer fungerar.
Och skulle du trots allt lyckas, på något mirakulöst sätt, så skulle mängder av C programmerare bli överlyckliga.

Hur har Rust löst problemet med överindexering?

Permalänk
Medlem
Skrivet av heretic16:

Fortran är säkert mycket snabbt. Varför vet jag inte. Men jag ser dock ingen användning utav Fortran alls.

Det är för att du inte tittar på rätt ställen. Bland hobby-användare är det inte så vanligt, men för tekniska och vetenskapliga beräkningar används det fortfarande flitigt. Ungefär samma ställen som där Matlab används mycket.

Permalänk
Medlem
Skrivet av heretic16:

Varför skulle den bli ogiltig? Jag har inte förstått detta. Så länge man inte rör syntaxen så anser jag att koden är helt enkelt orörd. Det är bara kompilatorn som har blivit smartare.

C definierar vad som skall hända när man kör en viss kod. Resultat kan vara odefinierat, men specen är tydlig med vad som är det. Skriver du ett program som är giltigt enligt specen så skall resultatet bli precis likadant varje gång, oavsett vilken kompilator man använder.

Det går idag att skriva kod som är helt laglig och korrekt C, men som är osäker. Vad skall kompilatorn göra med den koden? Specen säger att om koden är att du skall skriva till en adress och fortsätta tills buffern är slut, så skall programmet också göra det, oavsett hur mycket minne som är allokerat. Att göra något annat bryter mot specen.

Visa signatur

5900X | 6700XT

Permalänk
Skrivet av mpat:

C definierar vad som skall hända när man kör en viss kod. Resultat kan vara odefinierat, men specen är tydlig med vad som är det. Skriver du ett program som är giltigt enligt specen så skall resultatet bli precis likadant varje gång, oavsett vilken kompilator man använder.

Det går idag att skriva kod som är helt laglig och korrekt C, men som är osäker. Vad skall kompilatorn göra med den koden? Specen säger att om koden är att du skall skriva till en adress och fortsätta tills buffern är slut, så skall programmet också göra det, oavsett hur mycket minne som är allokerat. Att göra något annat bryter mot specen.

Jag förstår inte vad du menar.
Vi tar det från börjar.

En for-sats genererar en viss assembler-kod.
Om jag överindexerar denna for-sats så kan vad som helst hända.

Om jag hade ett program som kunde säga åt mig att "Du överindexerar på rad 20 - Error" så förändrar jag inte min assembler-kod, utan programmet bara säger åt programmeraren att något är på tok.

Permalänk
Medlem
Skrivet av heretic16:

Hur har Rust löst problemet med överindexering?

Det har det väl egentligen inte.
Om inte kompilatorn kan bevisa att en indexering är korrekt, så görs kontrollen vid runtime så att programmet kraschar vid en felindexering istället för att läsa/skriva till en felaktig minnesposition. Det är en viktig skillnad mot C där i princip vad som helst kan hända vid en felindexering.
För de flesta fall kan man göra likadant i en C kompilator, men där kan det vara svårare att avgöra vilka indexeringar som är korrekta och vilka som inte är det.

Permalänk
Medlem
Skrivet av heretic16:

Jag förstår inte vad du menar.
Vi tar det från börjar.

En for-sats genererar en viss assembler-kod.
Om jag överindexerar denna for-sats så kan vad som helst hända.

Om jag hade ett program som kunde säga åt mig att "Du överindexerar på rad 20 - Error" så förändrar jag inte min assembler-kod, utan programmet bara säger åt programmeraren att något är på tok.

Men det är inte att göra programspråket säkert, det är en statisk analys i kompilatorn. Det gör alla kompilatorer idag, och har gjort länge. Problemet är att detta aldrig kommer att vara heltäckande. Det är matematiskt bevisat att ett programs beteende aldrig kan förutsägas 100% på något annat sätt än att köra det. Se The Halting Problem för ett känt exempel.

https://en.wikipedia.org/wiki/Halting_problem

Visa signatur

5900X | 6700XT

Permalänk
Hedersmedlem
Skrivet av heretic16:

Om jag hade ett program som kunde säga åt mig att "Du överindexerar på rad 20 - Error" så förändrar jag inte min assembler-kod, utan programmet bara säger åt programmeraren att något är på tok.

För vissa fall kan väl gcc faktiskt detta:

int main(int argc, char** argv) { int a[10]; for(int i = 0; i < 11; ++i) a[i] = 0; return 0; }

gcc test.c -O2 test.c: In function ‘main’: test.c:5:22: warning: iteration 10 invokes undefined behavior [-Waggressive-loop-optimizations] 5 | a[i] = 0; | ~~~~~^~~ test.c:4:26: note: within this loop 4 | for(int i = 0; i < 11; ++i) | ~~^~~~

men i det allmänna fallet (med en godtycklig pekare som man har fått från någon annan funktion och index som beror av saker som inte är kända vid kompilering) är det inte så enkelt. Man vill ju inte heller ge falsklarm.

Permalänk
Skrivet av Elgot:

För vissa fall kan väl gcc faktiskt detta:

int main(int argc, char** argv) { int a[10]; for(int i = 0; i < 11; ++i) a[i] = 0; return 0; }

gcc test.c -O2 test.c: In function ‘main’: test.c:5:22: warning: iteration 10 invokes undefined behavior [-Waggressive-loop-optimizations] 5 | a[i] = 0; | ~~~~~^~~ test.c:4:26: note: within this loop 4 | for(int i = 0; i < 11; ++i) | ~~^~~~

men i det allmänna fallet (med en godtycklig pekare som man har fått från någon annan funktion och index som beror av saker som inte är kända vid kompilering) är det inte så enkelt. Man vill ju inte heller ge falsklarm.

Hur skulle det sett ut om du gjorde så här?

#include <stdio.h> int main() { int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *B = A; for(int i = 0; i < 11; i++){ printf("%i ", B[i]); } return 0; }

Permalänk
Hedersmedlem
Skrivet av heretic16:

Hur skulle det sett ut om du gjorde så här?

#include <stdio.h> int main() { int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *B = A; for(int i = 0; i < 11; i++){ printf("%i ", B[i]); } return 0; }

Det ger ingen varning.

Permalänk
Skrivet av Elgot:

Det ger ingen varning.

Hade det gett en varning i Rust?

Permalänk
Hedersmedlem
Skrivet av heretic16:

Hade det gett en varning i Rust?

Jag är ingen rust-auktoritet, men jag tror inte det. Däremot tror jag att det pålitligt upptäcks vid körning.
Sedan skiljer sig ju praxis en del mellan språken. Det är kanske ovanligt att man skriver något som ditt exempel i typisk rust-kod.

Permalänk
Medlem
Skrivet av Elgot:

Jag är ingen rust-auktoritet, men jag tror inte det. Däremot tror jag att det pålitligt upptäcks vid körning.
Sedan skiljer sig ju praxis en del mellan språken. Det är kanske ovanligt att man skriver något som ditt exempel i typisk rust-kod.

Det är ovanligt att man skriver något sådant i något språk. Men mer komplicerade fall som triggar samma typ av problem finns ju.

Permalänk
Datavetare
Skrivet av heretic16:

Hur skulle det sett ut om du gjorde så här?

#include <stdio.h> int main() { int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *B = A; for(int i = 0; i < 11; i++){ printf("%i ", B[i]); } return 0; }

I C99 är det både giltigt och i många fall rätt användbart att använda sig av denna typ av konstruktion

struct some_hw_memory_mapping { int a; char v[0]; }; void do_something_with_hw(struct some_hw_memory_mapping *dev) { if (dev->a == 42) dev->v[10] = 'A'; else dev->v[0] = 'B'; }

Att deklarera en array med storlek noll säger: anta att det finns ett gäng element av den här typen, går inte säga hur många.

Är totalt omöjligt för kompilatorn eller verktyg som utför statisk analys om kommer läsa/skriva utanför giltigt område. "Fixar" man detta blir det en bakåtinkompatibel förändring av språket.

Rust kan naturligtvis inte heller hantera fallet ovan "automagiskt". Lösningen där är att man explicit måste markera sådana regioner i koden som unsafe. Vinsten där är om man får en "out-of-bounds" krasch så måste den vara orsakad av något markerat som unsafe då övrig kod endera upptäcker problemet vid kompilering alt. (som fel-indexera en array) upptäcks runtime.

Ett annat exempel som man inte kan fixa i C/C++ med mindre än att bryta bakåtkompatibilitet och som gör det möjligt för kompilatorn att i vissa lägen producera bättre kod i Rust är detta exempel

C alt. C++

void compute(int *a, int *b, const int * c) { *a += *c; *b += *c; }

ger detta med -O2 på x86

compute(int*, int*, const int *): mov eax, DWORD PTR [rdx] add DWORD PTR [rdi], eax mov eax, DWORD PTR [rdx] add DWORD PTR [rsi], eax ret

Rust (semantisk så nära som möjligt fallet ovan)

pub fn compute(a: &mut u32, b: &mut u32, c: &u32) { *a += *c; *b += *c; }

ger detta

compute: mov eax, dword ptr [rdx] add dword ptr [rdi], eax add dword ptr [rsi], eax ret

Orsaken är att Rust förbjuder två minnesreferenser att överlappa medan det är tillåtet i C och C++. De flesta C/C++ kompilatorer har flaggor som säger "anta att jag aldrig har överlappande minnesreferenser", men det är strikt utanför specifikation.

Ovan är bara några exempel på saker man kan fixa genom att skapa nya språk/språkversioner, men som inte kan fixas i existerande språk med mindre än att paja bakåtkompatibilitet i någon mån.

Det sista är något man nu tänkt på i Rust! Där finns konceptet av Editions. Problemen ovan kan inte fixas i en existerande Edition, idag finns Rust Edition 2015, 2018 och 2021.

Dessa är inte jämförbara med C++11/14/17/21 etc då C++21 måste vara helt kompatibel med föregående versioner.

"Tricket" i Rust är att varje "crate" (tänk bibliotek) specificerar vilken Rust edition den använder. Alla icke-triviala program består av flera "crates", det är explicit tillåtet att ett program använder "crates" som använder sig av olika editions. Sättet miljön är designad säkerställer att anropen mellan fungerar. Vad man praktiken gjort är en väldefinierad metod för att ha flera olika språkversioner i samma program på ett kompatibelt sätt.

Skrivet av heretic16:

Hade det gett en varning i Rust?

Det hade inte att gått att göra på samma sätt inom ramen av "safe" Rust då man inte tillåter pekar-aritmetik där (är bara tillåtet i unsafe Rust). Närmaste översättningen skulle kunna se ut t.ex. så här

Gör man såhär upptäcks problemet med statisk analys (man får en varning i VS Code om att man kommer indexera utanför)

fn main() { let a:[u32; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; for i in 0..11 { let b = &a[i]; print!("{} ", *b); } }

med denna modifiering blir det ingen varning i IDE, men blir "panic" vid körning

fn get_ref<'a>(xs: &'a [u32; 10], index: usize) -> &'a u32 { &xs[index] } fn main() { let a:[u32; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; for i in 0..11 { let b = get_ref(&a, i); print!("{} ", *b); } }

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Hedersmedlem
Skrivet av Elgot:

Det är kanske ovanligt att man skriver något som ditt exempel i typisk rust-kod.

Ja, precis.
Normalt skulle man väl göra en for-loop, som i Rust alltid är itererande som foreach:

fn main() { let A = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; for i in A { print!("{} ", i); } }

Inte heller är det några problem att lägga till en pekare, förstås:

fn main() { let A = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let B = &A; for i in B { print!("{} ", i); } }

Men om man verkligen vill bryta mot alla regler hur språket är tänkt att användas då...

fn main() { let A = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let B = &A; let mut i = 0; loop { print!("{} ", B[i]); i += 1; if i > 10 { break; } } }

$ ./test.exe thread 'main' panicked at 'index out of bounds: the len is 10 but the index is 10', test.rs:6:23 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace 1 2 3 4 5 6 7 8 9 10

Mår lite dåligt av att ha skrivit den koden dock, tror inte ens att såna loopar skulle användas i kernelprogrammering eller liknande.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

Permalänk
Skrivet av Yoshman:

Orsaken är att Rust förbjuder två minnesreferenser att överlappa medan det är tillåtet i C och C++. De flesta C/C++ kompilatorer har flaggor som säger "anta att jag aldrig har överlappande minnesreferenser", men det är strikt utanför specifikation.

Ovan är bara några exempel på saker man kan fixa genom att skapa nya språk/språkversioner, men som inte kan fixas i existerande språk med mindre än att paja bakåtkompatibilitet i någon mån.

Det sista är något man nu tänkt på i Rust! Där finns konceptet av Editions. Problemen ovan kan inte fixas i en existerande Edition, idag finns Rust Edition 2015, 2018 och 2021.

Dessa är inte jämförbara med C++11/14/17/21 etc då C++21 måste vara helt kompatibel med föregående versioner.

"Tricket" i Rust är att varje "crate" (tänk bibliotek) specificerar vilken Rust edition den använder. Alla icke-triviala program består av flera "crates", det är explicit tillåtet att ett program använder "crates" som använder sig av olika editions. Sättet miljön är designad säkerställer att anropen mellan fungerar. Vad man praktiken gjort är en väldefinierad metod för att ha flera olika språkversioner i samma program på ett kompatibelt sätt.

Det hade inte att gått att göra på samma sätt inom ramen av "safe" Rust då man inte tillåter pekar-aritmetik där (är bara tillåtet i unsafe Rust). Närmaste översättningen skulle kunna se ut t.ex. så här

Jag kan inte avgöra fördelar och nackdelar i ditt inlägg.
Jag tycker Rust imponeras att den genererar mindre assemblerkod. Detta finner jag väldigt världefullt.

Jag hittar dock inga jobb inom Rust för inbyggda system. Alltså riktiga inbyggda system, inte någon Raspberry Pi server...

Permalänk
Medlem

Nu har jag tagit en 15-minuter kurs i Rust pekare och vad jag uppfattade är att man har olika typer av pekare där vissa är smarta, medans andra räknas som "raw" och skall deklareras med "unsafe". Tycks mig att man infört nya ramar som hårdare kontrollerar programmerarens intentioner. Däremot kan man med "raw" pekarna fortfarande göra samma dumheter som man alltid kunnat göra i C

Skrivet av Erik_T:

För att göra C säkert skulle du behöva ändra språket så mycket att det inte längre skulle vara C. Mängder av existerande kod skulle bli ogiltig.
Det räcker inte att bara förbättra kompilatorn - om det vore så enkelt så garanterar jag att det redan skulle gjorts.

Det är så enkelt och det har redan införts i gcc: -Warray-bounds (eller -Wall).
Helt utan förändringar i källkoden. Det räcker att det sker i kulisserna genom assemblerkod genererad av kompilatorn.

Sen är det ju upp till användarna att slå på denna utökning, samt att kompilatorutvecklarna utökar finesserna med tiden. Tyvärr är det väl en av källorna till alla nya språk; det går fortare att skapa ett nytt språk än att tröska förbättringar genom standardorganen.

Permalänk
Hedersmedlem
Skrivet av mc68000:

Nu har jag tagit en 15-minuter kurs i Rust pekare och vad jag uppfattade är att man har olika typer av pekare där vissa är smarta, medans andra räknas som "raw" och skall deklareras med "unsafe". Tycks mig att man infört nya ramar som hårdare kontrollerar programmerarens intentioner. Däremot kan man med "raw" pekarna fortfarande göra samma dumheter som man alltid kunnat göra i C

Dock värt att nämna att "råa" pekare sällan behövs i vanliga program. Du kan göra det allra mesta utan att använda unsafe någonstans i din kod.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

Permalänk

På tal om säkerhet.

Smarta pekare används inom C++, dock inte inom C då smarta pekare är nytt. Men hur fungerar smarta pekare, förutom att det är ett säkert sätt att säga "new" ?

Varför just smarta pekare nu, men inte förr?

Permalänk
Medlem
Skrivet av mc68000:

Nu har jag tagit en 15-minuter kurs i Rust pekare och vad jag uppfattade är att man har olika typer av pekare där vissa är smarta, medans andra räknas som "raw" och skall deklareras med "unsafe". Tycks mig att man infört nya ramar som hårdare kontrollerar programmerarens intentioner. Däremot kan man med "raw" pekarna fortfarande göra samma dumheter som man alltid kunnat göra i C

Kör man med "unsafe" i Rust så försvinner alla säkerhetsgarantier. Bör endast användas där det inte går att lösa problemet på annat sätt, vilket är rätt sällsynt.

Men i normal Rust så är pekare inte smarta som sådana, utan reglerna för språket gör att man inte kan de-referera en pekare som pekar på ett icke-existerande objekt (t.ex. null-pekare eller en pekare till frigjort minne)
Just den typen av säkerhet vid minneshantering förefaller vara den största förbättringen med Rust jämfört med äldre språk.
Att det även undviker vissa fall av fel-indexering i faktiskt existerande arrayer är mest en bonus, inte huvudpoängen.

Citat:

Det är så enkelt och det har redan införts i gcc: -Warray-bounds (eller -Wall).
Helt utan förändringar i källkoden. Det räcker att det sker i kulisserna genom assemblerkod genererad av kompilatorn.

-Warray-bounds och -Wall gör ingenting med den genererade assemblerkoden, utan slår bara på vissa varningar som ändå inte fångar alla instanser av fel-indexering. (Alternativt varnar även för korrekt kod som kompliatorn inte kan visa är korrekt.)