Von C zu Rust wechseln?





  • Der Grund, weshalb rust erfolgreich sein wird, ist, dass genügend Leute an den Erfolg glauben. D. h., sie werden die Programmiersprache einfach nutzen. Es existiert ja schon jetzt ein brauchbares Buildsystem. Es fängt also schon mit der Tool-Chain an. Außerdem gibt es eine llvm-Integration. Und das Interesse hier im Forum ist auch ein Anzeichen dafür, dass manche C++ endlich abgelöst sehen wollen.



  • Also wird Rust so erfolgreich wie Prolog und Haskell? Wobei, die taugen als Lehrsprachen von daher werden sie durch Universitäten verbreitet, Rust taugt dafür eher schlecht.



  • Du scheinst es nicht verstanden zu haben. Rust taugt als C++ Ersatz. :p



  • Und du meinst man hat Lust auf eine neue Krankheit, die man mit sich herumschleppen muss? 😞



  • Du scheinst es nicht verstanden zu haben. Rust ist perfekt.

    Ok, sorry, der musste sein.



  • @Ethon: Du musst blind sein. Rust ist der einzige weg in eine bessere Zukunft!

    ~@dot: 😃 yay!~



  • Wieviel Performance bzw. Rechenzyklen kostet denn diese ganze Sicherheit, die Rust bieten soll?

    Was soll hier ein Entwickler machen, für den die Geschwindigkeit wichtig ist?



  • asfdlol schrieb:

    An dieser Knacknuss war ich gestern den ganzen Tag dran:

    int* Datas = new int(0);
    try
    {
    	std::cin >> *reinterpret_cast<int*>(&Datas);
    }
    catch(...)
    {
    	std::cerr << "Fehler aufgetreten, Programm wird terminiert!" << std::endl << std::endl;
    	delete Datas;
    	return -1;
    }
    f(*Datas);
    delete Datas;
    

    In Java oder in Rust wäre mir das nicht passiert...

    Wenn das kein Scherz ist, dann musst du ganz dringend eines von zwei Dingen tun:

    1. Lern C++
    2. Lass C++ bleiben


  • Elliosso schrieb:

    Wieviel Performance bzw. Rechenzyklen kostet denn diese ganze Sicherheit, die Rust bieten soll?

    So gut wie gar nichts. Temporale Speichersicherheit ist eine Sache, die komplett zur Übersetzungszeit gewährleistet wird, also ohne Laufzeitchecks auskommt. Spatiale Speichersicherheit wird, falls nötig, über Laufzeitchecks erhalten. Wenn solche Checks irgendwo stattfinden, weil sie nicht wegoptimiert wurden, dann fallen sie trotzdem nicht besonders ins Gewicht, wenn man das mal mit SoftBound+CTS vergleicht; denn in Rust gibt es keine Zeigerarithmetik im herkömmlichen Sinne, die solche Checks kompliziert werden lassen würden (Shadow Tables und co). In Rust arbeitet man in der Hinsicht mit „Slices“. Das sind „fette Zeiger“, die nicht nur auf ein einzelnes Element sondern quasi auf einen ganzen Bereich zeigen, den man nur verkleinern darf. Das einfache Iterieren über ein Array ist z.B. genauso billig wie in C, wenn man das idiomatisch über Iteratoren macht.

    Elliosso schrieb:

    Was soll hier ein Entwickler machen, für den die Geschwindigkeit wichtig ist?

    Was soll der schon machen? Deine Frage setzt voraus, dass Rust vom Sprachdesign her in der Hinsicht ein Problem hätte. Das hat es nicht. Diejenigen, denen Geschwindigkeit wichtig ist, werden nicht unbedingt ein Problem mit Rust haben. Und wenn sie z.B. über einen Profiler doch feststellen, dass das Bounds Checking an irgendeiner heißen Stelle wirklich stört, dann hoffe ich doch mal, dass in der Lage sind, diese Situation richtig zu bewerten. Zur Not gibt es eben noch get_unchecked , worüber man Slice-Elemente ohne Bounds-Checking in unsafe -Blöcken dereferenzieren kann. Das vergrößert natürlich die Angriffsfläche. Wenn man da etwas falsch macht, ist es hin mit den Sicherheitsgarantien.

    Ich finde, das ist ein sehr guter Kompromiss. Die Stellen, wo man Fehler machen kann, die Löcher in die Speichersicherheit reißen würden, sind klar als solche zu erkennen ( unsafe -Blöcke) und sollten nur einen sehr kleinen Teil des kompletten Codes ausmachen, wenn es sie überhaupt in einem Projekt gibt. Es bietet sich auch eine automatisierte Vollstreckung einer Review-Policy an, die verlangt, dass ein zusätzlicher Reviewer nochmal über den Code rüber schaut, wenn ein unsafe -Block bei einer Änderung angefasst oder neu eingeführt wurde.



  • Mal ne GANZ doofe Frage: wie geht Rust mit Kopien von immutable Typen wie z.B. (hoffentlich) Strings um? Ref-Counting? Per Library oder eingebaut? Ganz was anderes?



  • hustbaer schrieb:

    Mal ne GANZ doofe Frage: wie geht Rust mit Kopien von immutable Typen wie z.B. (hoffentlich) Strings um? Ref-Counting? Per Library oder eingebaut? Ganz was anderes?

    Wenn man nicht kopiert, sondern

    let x = irgendeinString;
    

    schreibt, wird das per move gemacht. Meistens benutzt man aber string-slices, diese bieten naemlich die gleichen operationen wie immutable strings und sind sowas wie std::string_view, aber besser in die Sprache integriert. String literale sind zum Beispiel string slices und so ersetzen sie const char* im Anwendercode komplett. Erst dann, wenn ein String kopiert wird (explizit mit .clone()), wird wirklich Speicher reserviert.
    Alleine dadurch braucht man kaum noch kopien. Ansonsten ist vieles noch nicht fertig und so sind strings zur Zeit intern noch durch ein std::Vec<u8> repraesentiert. Ich vermute, dass mindestens small string optimization noch irgendwann kommen wird.



  • Ich meine wenn man ein immutable Objekt an mehrere Stellen übergibt.
    Kopieren ist ja eher ineffizient, speziell wenn man dafür dynamisch Speicher besorgen muss.

    Muss ja irgend einen Mechanismus geben es ohne Kopieren mehreren Stellen zugänglich zu machen.
    => wie?



  • hustbaer schrieb:

    Ich meine wenn man ein immutable Objekt an mehrere Stellen übergibt.
    Kopieren ist ja eher ineffizient, speziell wenn man dafür dynamisch Speicher besorgen muss.

    Muss ja irgend einen Mechanismus geben es ohne Kopieren mehreren Stellen zugänglich zu machen.
    => wie?

    (Ich nehmen an du meinst zur Laufzeit erstellte Objekte, die immutable sein sollen)

    Da ist nichts automatisch, der Entwickler muss den Ownership selber festlegen. Wenn gewünscht ist, dass es geshared wird, dann nimmt er halt den nicht-threadsicheren shared_ptr oder den threadsicheren shared_ptr. Beide beinhalten immutable Daten.



  • hustbaer, fragst Du dich gerade nach dem Äquivalent von "const T&"? Falls ja: Das gibt's natürlich auch, nennt sich "borrowing":

    …
        let mut phonebook = HashMap::new();
        …
        foo(&phonebook);
        // phonebook is still valid at this point
        foo(&phonebook);
        …
    
    fn foo(x: &HashMap<String,String>) {
        for (k, v) in x {
            println!("{}: {}", *k, *v);
        }
    }
    

    playpen-Link

    Wenn Du jetzt eher in Richtung shared_ptr gehen willst, geht das auch:

    use std::rc::Rc;
    
    fn main() {
        let s = Rc::new("Hallo Welt".to_string());
        foo(s.clone()); // <-- clone will refer to the same object
        println!("{}", *s); // <-- s is still valid here
    }
    
    fn foo(s: Rc<String>) {
        println!("{}", *s);
    }
    

    playpen-Link

    Statt Rc<T> (reference-counted) gibt es noch Arc<T> (atomically reference-counted), mit dem man dann auch über Thread-Grenzen hinweg kann, sofern TSync ist“, also sicher von mehreren Threads aus „lesbar“ ist.

    Der Unterschied zwischen &T und Rc<T> ist natürlich, dass &T nicht besitzend sondern nur „ausgeliehen“ ist. Beide Arten von Zeigern lassen sich aber vervielfältigen (mit clone() und im ersten Falle auch ohne, weil er trivial kopierbar ist).

    Bei Vektoren und Strings gibt es noch eine andere Art des Ausleihens. Statt &Vec<T> und &String sollte man &[T] und &str verwenden, weil sie allgemeiner sind und sich nicht unbedingt auf das Innere eines Vec s oder String s beziehen müssen. Zeichenkettenliterale sind z.B. vom Typ &str . Das schöne ist, dass diese Typen besonders gut zusammen arbeiten. So ist es z.B. möglich, für das Lookup in der obigen HashMap auch einfach &str statt &String als Argumenttyp zu verwenden (weil man sich ein String -Objekt in Form eines &str „ausleihen“ kann). Ein Wert des Typs &str ist im Prinzip eine Anfangsspeicheradresse gepaart mit einer Länge, die angibt, wieviele UTF8 code units darüber addressierbar sind. &[T] ist ähnlich (Adresse + Länge). Der Unterschied zwischen str und [u8] ist aber, dass bei str garantiert wird, dass es sich um eine korrekt kodierte UTF8 Zeichenkette handelt. &str und &[T] sind diese „Slices“ oder „fat pointers“, von denen ich im vorherigen Beitrag sprach.



  • Rc<T> bzw. Arc<T> war das was ich wissen wollte.
    Also auf Library-Ebene behandelt. Schade.
    Ich glaube nämlich dass es gescheiter wäre das der VM/Runtime aufs Auge zu drücken, da man dann mehr Möglichkeiten zur Optimierung hat.



  • Es soll bald auch Gc<T> geben.



  • ownie schrieb:

    Es soll bald auch Gc<T> geben.

    Nicht mehr. Gc wurde nie vollstaendig implementiert, hat immer mit referenz-zaehlen gearbeitet und wurde irgendwann entfernt. Das war sogar schon deutlich laenger geplant, wurde aber nicht gemacht, weil es noch code in Servo und rustc gab, die gc brauchten.



  • hustbaer schrieb:

    Rc<T> bzw. Arc<T> war das was ich wissen wollte.
    Also auf Library-Ebene behandelt. Schade.

    Nee... Gut so! Es hat in Rust so angefangen, wie Du es für besser hältst. Aber man will eben auch für eine „Systemprogrammiersprache“ eine minimale Runtime haben. Und der Sprachkern war dann irgendwann mächtig genug, dass man es in Form einer Bibliothek anbieten konnte.

    hustbaer schrieb:

    Ich glaube nämlich dass es gescheiter wäre das der VM/Runtime aufs Auge zu drücken, da man dann mehr Möglichkeiten zur Optimierung hat.

    Und ich glaube, dass das überhaupt gar keine Rolle spielt. Shared ownership benutze ich selten bis gar nicht. Wo siehst Du denn da Optimierungspotential?



  • Interessanter Vortrag über Servo.
    Leider haben die zu weniger Entwicklerresourcen. Vielleicht will einer von euch mithelfen kleinere Aufgaben zu implementieren? Einigen von euch traue ich das zu!

    https://www.youtube.com/watch?v=7q9vIMXSTzc

    Viele der noch umzusetzenden Elemente sind aber eher einfache Kopien aus den jeweiligen Spezifikationen, weshalb auch viele Studenten Code als Kursaufgaben beitragen, wie Matthews erklärt.

    http://www.golem.de/news/mozilla-servo-der-wikipedia-browser-1502-112145.html


Anmelden zum Antworten