Undefinierte variablen bringen zum Absturz. Wozu ?



  • achso hm hm

    Vielleicht ist der Sinn dafür:

    wenn ich nicht initialisere

    int a = 123;
    int b;
    int c;
    int d;
    int e;
    
    b=a;
    c=b;
    d=c;
    e=d;
    

    würde schneller laufen als

    bool a = 123;
    int b = 0;
    int c = 0;
    int d = 0;
    int e = 0;
    
    b=a;
    c=b;
    d=c;
    e=d;
    

    weil hier einmal auf die nullern zuweisen muss dann auf 123. -> mehr rechenleistung?



  • Von der Geschwindigkeit her bringt DAS keinen Unterschied (vor allem, weil es für die Zuweisung egal ist, welcher Wert voerher in der Zielvariablen stand). Das einzige, was schneller sein kann, wäre so etwas:

    int a = 123;
    int b = a;
    int c = b;
    int d = c;
    int e = d;
    

    (damit ersparst du dir die nachträglichen Zuweisungen)

    Problematisch werden nicht initialisierte Variablen wie gesagt erst, wenn du ihren (noch nicht festgelegten) Wert verwenden willst.



  • CStoll, ich glaube, du hast ihn falsch verstanden. Er hat nämlich nicht ganz unrecht:

    int x = 15; // Für 15 Datensätze vorbereiten
    int x = getActualNum() + 200; // Für 200 zusätzliche Datensätze vorbereiten
    int x = -1; // < 0 = unbekannte Anzahl, zur Laufzeit kontinuierlich nachallokieren
    int y = 0; // Leer
    int y = getDiscardedNum(); // Anzahl gelöschter Datensätze
    

    Wenn ich eine Variable anlege, so initialisiert der Compiler diese nicht. Er warnt lediglich, wenn ich eine Variable lese, ohne sie zuvor geschrieben zu haben.

    Der Compiler initialisiert sie nicht, da er nicht wissen kann, mit welchem Wert sie initialisiert werden muss. Er KÖNNTE alle Variablen mit 0 initialisieren, das sind aber zusätzliche Operationen, und wie man oben sieht, kann es durchaus sein, daß nur ein Bruchteil der Variablen mit 0 initialisiert wird.

    Das bedeutet aber auch, daß die Variablen jeden möglichen Zustand haben könnten.

    Es ist also durchaus legitim, anzunehmen, daß der Compiler die Variablen aus Geschwindigkeitsgründen nicht initialisiert (man stelle sich hier eine rekursive Funktion mit mehreren lokalen Variablen vor).



  • @xBlackKnightx:
    Über den Sinn kann man streiten, ich denke die Sache kommt in C++ einfach daher dass C++ von C abstammt, und man in C lokale Variablen nur am Anfang eines Blocks definieren konnte. Da dort aber nicht unbedingt für alle Variablen die man später braucht ein sinnvoller Wert zur Verfügung steht, z.B. weil man erst noch irgendetwas checken muss bevor der feststeht, bringt es ja auch nix schon was reinzuschreiben.
    Davon abgesehen war zu der Zeit als C "gemacht wurde" das Thema "sicheres Programmieren" noch lange nicht so interessant/"in"/aktuell/... wie heute, man hat sich über soetwas also nicht lange den Kopf zerbrochen wenn ich es mal so sagen darf.

    In deinem Beispiel hier

    bool a = 123;
    int b = 0;
    int c = 0;
    int d = 0;
    int e = 0;
    
    b=a;
    c=b;
    d=c;
    e=d;
    

    (abgesehen davon dass 123 zu 1 wird, weil bool bloss 0 oder 1 halten kann), kannst du das ruhig so machen, da so gut wie jeder Compiler die "unnötigen" Initialisierungen von b, c, d und e wegoptimieren wird. Wenn du die Variablen nicht verwendest wird er wahrscheinlich sogar die ganzen Variablen wegoptimieren.

    Langer Rede kurzer Sinn, du kannst (solange es einfach nur ints oder bools oder doubles oder sowas sind) ruhig immer alles initialisieren, es wird deswegen nicht langsamer.

    Und weil du "bool" angesprochen hast: C++ verlangt nicht dass folgender Code nur 0 oder 1 ausspuckt:

    void foo()
    {
        bool x;
        int y = x;
        printf("%d\n", y);
    }
    

    In dem Fall darf ein Compiler Code generieren der u.U. 42 ausspuckt. Ein "bool" darf zwar nur 0 oder 1 sein, aber das gilt nur für initialisierte bools. Soll heissen: der Compiler muss quasi nur beim Schreiben in das bool den Wert auf 0 oder 1 "zwingen", beim lesen liest er einfach das was drinsteht, und das kann eben irgendeine Zahl sein, wenn die Variable nicht initialisiert wurde.

    Wenn du allerdings statt "bool x;" etwas wie "bool x = rand();" schreibst, dann darf laut Standard nur 0 oder 1 ausgegeben werden.

    ----

    C++ ist und bleibt ein "schiess dir bitte in den Fuss" Instrument, und man muss halt leider verflixt aufpassen was man damit tut. Gute Compiler liefern aber heutzutage gottseidank eine Warning wenn man offensichtlich eine Variable liest bevor man sie das erste mal geschrieben (=initialisiert) hat.



  • ups das mit bool hab ich wohl vertippt, sollte eigentlich auch int sein. war aber wohl trotzdem verständlich.

    ja ich merk schon, c++ mag eine sehr alte sprache sein im gegensatz zu php & co.

    Ich dachte an Entwicklungsumgebung die auf so etwas aufpassen können. Wenn ich z.b. irgenein Text "sadfj" reinschreibe, dann markiert das Programm den text rot, ohne dass der Compiler das erst melden muss. Erst wenn ich "int" davor schreibe, wird sie gültig. Andere Ideen wären z.b. per Tastaturkürzel eine fertige for-Schleife hinkopieren, der Hintergrund in Zeilen von offene bis geschlossene geschweifte Klammer werden dunkler gefärbt. So alles durch grafische Hervorhebungen besser erkennbar machen. Und wenn ich eine der Klammern weglösche, verschwindet auch das andere usw... Gibt es vielleicht solche Programme? oder kann man das in VC 8 irgendwie freischalten? Ansonsten könnte man so eine Entwicklungsumgebung selber schreiben, den Compiler von g++ nehmen. Nur kann ich so etwas noch nicht. würde aber gern bald so eins schreiben. Naja dann lern ich mal C++ weiter...

    grüsse



  • gibts doch schon alles.

    zb macht der BCB bei jeder quellcode änderung eine syntaxüberprüfung, und streicht fehler an.

    Dann kann dir fast jede ide mit tastaturkürzel grundstrukturen für klassen, schleifen, if abfragen etc erstellen.

    Am ende sind diese Hilfen aber schon fast wieder sinnlos, weil die meisten Fehler, die so entdeckt werden, fehler sind, die man auch selbst innerhalb weniger sekunden finden kann. Bzw es sind fehler, die man mit einem bestimmten erfahrungsschatz nurnoch aus schusseligkeit macht. Das mäkelt der Compiler im zweifelsfall einmal an, und dann ist gut.

    Schlimmer finde ich da schon eine ide, die durch ständige überprüfungen etc anfängt zu ruckeln...



  • Naja, in C++ dauert eine vollständige Syntaxüberprüfung "ewig". Wir haben in der Firma z.T. einzelne C++ Files die > 10 Sekunden zum compilieren brauchen, auf 2,8GHz Pentiums mit 1GB RAM. Würde die IDE das machen wollen während ich programmiere ... würde das wohl etwas stören 🙂

    p.S.: diese Files sind garnicht unbedingt gross, ein bisschen Boost.Bind da, ein wenig Boost.Function dort, noch eine Prise Boost.MultiIndex drübergestreut -> fertig 🙂



  • Lecker Boost Süppchen 😋

    Woher kommen eigentlich die "zufälligen" Werte der nicht initialisierten Variablen? Sind das einfach die Bits, die zuletzt an der Speicheradresse gestanden sind?



  • Woher kommen eigentlich die "zufälligen" Werte der nicht initialisierten Variablen? Sind das einfach die Bits, die zuletzt an der Speicheradresse gestanden sind?

    Genau. Woher sonst 😉

    BTW: MSVC macht im Debug Mode alle nicht initialisierten lokalen Variablen mit dem Bytemuster 0xcc voll, alles was mit new/new[]/malloc angelegt wurde und nicht initialisiert mit 0xcd, und alles was mit delete/delete[]/free freigegeben wird wird mit 0xee angefüllt. Wenn man beim Debuggen über so einen Wert stolpert ist das ein guter Hinweis darauf dass man wo eine nicht initialisierte Variable bzw. einen "dangling pointer" hat.
    Und im Release Mode steht dann eben das drinnen was immer zuvor an der Speicheradresse stand, bzw. nach einem delete/delete[]/free steht halt immer noch das dort was vorher dort stand.



  • hustbaer schrieb:

    Naja, in C++ dauert eine vollständige Syntaxüberprüfung "ewig". Wir haben in der Firma z.T. einzelne C++ Files die > 10 Sekunden zum compilieren brauchen, auf 2,8GHz Pentiums mit 1GB RAM. Würde die IDE das machen wollen während ich programmiere ... würde das wohl etwas stören 🙂

    Ja, einige Grundstrukturen (wie fehlende ; oder falsche Verschachtelungen) kann man zur Not in "Echtzeit" kontrollieren. Aber gerade wenn es um Templates geht, wird es aufwändig (kennst du die typischen Fehlermeldungen, wenn ein Template-Parameter irgendeine lokal verwendete Operation nicht verwenden kann? Das endet dann meistens in einer endlosen "instantiated from here" Liste).



  • @CStoll:
    Klar kenne ich die, hallo *winke-winke*, Boost User hier 🙂
    Ich kann aber ganz gut damit leben dass ich keine live Syntax überprüfung habe - so wie's in VB .NET implementiert ist nervt es mich sogar ziemlich.



  • Also mit PCH geht das kompilieren rattenschnell. Ich habe damals auch immer PCH abgeschaltet, weil ich in meinen Programmen keinen Compiletime-Vorteil erkannte. Aber ich hatte auch keine Templates und kein windows.h im Einsatz. 😉 Aber PCH verkürzt die Kompilierung bestimmt um 90%, nur der erste Compile-Durchlauf benötigt seine Zeit.

    Viele IDE-Features die man aus anderen Sprachen wie Java kennt, gibts auch für C++. Z.B. ist VisualAssist X ganz toll. Leider ist sowas nicht in MSVC serienmäßig. 😞 Was natürlich den Eindruck erweckt, das es sowas für C++ nicht gibt.

    Eine Livesyntax-Prüfung gibt es mittlerweile im Eclipse-C++!!! Zwar nicht so schnell wie unter Java, aber mit einer Verzögerung gibts dann auch die rot markierten Zeilen für C++.



  • *verdutzt guck*

    ich dachte immer, dass der Typ "bool" in C++ als "unsigned char" definiert ist, wonach die zuweisung von 123 gar nicht falsch ist ...



  • @Artchi:
    PCH ist im Einsatz, glaube mir. Das Erstellen der PCH braucht im übrigen schonmal > 1 Minute 😉



  • Checker&Murckser schrieb:

    ich dachte immer, dass der Typ "bool" in C++ als "unsigned char" definiert ist, wonach die zuweisung von 123 gar nicht falsch ist ...

    Wie bool intern definiert ist, wird im Standard nicht festgelegt - wichtig ist nur, daß es die zwei Werte 'true' (1) und 'false' (0) aufnehmen kann (deshalb sind auch die Optimierungen für vector<bool> oder bitset<> möglich).


Anmelden zum Antworten