Uninitialised value was created by a stack allocation



  • Ist die Ausgabe von valgrind eigentlich als Warnung oder wirklich als Fehler zu verstehen? Das Programm liefert ja richtige Ergebnisse.

    Von der Logik stimmt die Schleife ja. ncounter soll solange hochzählen bis er auf eine Zelle in basins findet die noch mit Null initialisiert ist. Wenn er die hat wird darin nattractor gespeichert. Danach wid das so gefundene ncounter zur Hilfsvaiabe ih1 gesetzt und in der fo Schleife in einen Vektor umgewandelt.

    Ich sehe das Problem doch nicht genau.



  • Ist die Ausgabe von valgrind eigentlich als Warnung oder wirklich als Fehler zu verstehen? Das Programm liefert ja richtige Ergebnisse.

    dein Code basiert auf undefiniertem Verhalten d.h. er ist falsch und "kann" jederzeit explodieren.

    Valgrind bemängelt das zu recht, probier mal den AddressSanitizer vom clang oder gcc - der beendet bestimmt dein Programm (völlig richtig) sofort beim ersten Problem

    die Sache mit dem "es läuft doch" solltest du dir bei C/C++ ganz ganz schnell abgewöhnen 🙂


  • Mod

    Noch ein bisschen umgeschrieben und Duplikate eliminert, und die Lösung wird offensichtlich:

    while ( ncounter < Var._SampleSize ) {
            neurons = TransferFunction::StepFunction( Update::Hebb( Matrix, neurons ) );
    
            int nNumber = ActivityToNumber( neurons );
    
            if ( basins[nNumber] == 0 ) {
                basins[nNumber] = nattractor;
            } else {
                if ( basins[nNumber] == nattractor ) {
                    if ( nattractor > 100 ) {
                        print << "Warning: attractor > 100";
                        exit( EXIT_FAILURE );
                    }
                    ++nattractor;
                } else {
                    for ( int i = 0; i <= ncounter; ++i ) {
                        if ( basins[i] == nattractor ) {
                            basins[i] = basins[nNumber];
                        }
                    }
                }
    
                if ( ++ncounter < Var._SampleSize ) {                                   // <===
                    basins[ncounter] = nattractor;
                }
    
                for ( int i = 0; i < Net._AdSize; ++i ) {
                    neurons[i] = ( ncounter & ( 1 << i ) ) != 0;
                }
            }
        }
    

    nattractor ist stets grösser 0, folglich führt Zeile 18 nie dazu, dass ein Element, dass 0 ist, geändert wird. Und umgekehrt wird ein Elemnt in dieser Zeile nie 0 gesetzt, weil der Fall basins[nNumber]==0 ja gleich am Anfang abgefangen wird.
    Daraus folgt, dass ncounter stets das letzte Element repräsentiert, dass nicht 0 ist. Also kann die Schleife

    while(basins[ncounter]>0){
    

    eliminiert werden. Ganz nebenbei bietet sich damit auch an, die Schleifenbedingung im else-else-Zweig anzupassen (Zeile 16) - weil nattractor>0 kann die Bedingung im if für die basins-Element hinter ncounter sowieso nicht zutreffen.



  • Hi

    Danke für die Mühe. Unglaublich wie kurz du diesen Code bekommen hast. Ich werde mir den Code genau ansehen.

    Wie ist dieser Fehler zu interpretieren? Sicher das ich nicht doch meine helpneurons benötige und das in zwei Schritte packen müsste?

    Attractor.cpp: In static member function ‘static void Attractor::AnalysisBinary(std::vector<std::vector<int> >&)’:
    Attractor.cpp:82:63: error: invalid initialization of non-const reference of type ‘std::vector<int>&’ from an rvalue of type ‘std::vector<int>’
             neurons = TransferFunction::StepFunction( Update::Hebb( Matrix, neurons ) );
    

    Grüße


  • Mod

    cpp_Jungspund schrieb:

    Wie ist dieser Fehler zu interpretieren?

    Interpretation: Du hast const correctness nicht beachtet. Oder der Begriff sagt dir gar nichts. In welchem Fall das natürlich schleunigst zu beheben ist.



  • Hi

    Unter const-correctness verstehe ich, dass alles was von der Logik des Programms her nicht verändert werden darf als const deklariert werden soll.

    Ich dachte das ist eine Leitidee, kein muss.

    Dementsprechend muss Matrix const sein? Und wieso heisst es im error non-const reference of type ‘std::vector<int>&’, da müsste doch die Matrix stehen. Das sieht aber eher so aus als wenn sich das auf neurons bezieht, was ja sicherlich nicht const ist.

    Das Schlüsselwort const in der Objektorientierung bereitet mir doch noch ein paar Verständnislücken. Ich lese dazu.


  • Mod

    cpp_Jungspund schrieb:

    Ich dachte das ist eine Leitidee, kein muss.

    Es ist auch kein Muss, aber es ist ansteckend. Wenn du einmal irgendwo ein const setzt oder ein konstantes Objekt benutzt, dann hat dies normalerweise zur Folge, dass du es dann überall richtig machen musst. Das ist eine gute Sache. Es hilft dir (oder eher dem Compiler) deine Logikfehler im Programm zu finden. Etwas das dir, ganz ehrlich gesagt, durchaus gut täte.

    Hier ist das erste const-Objekt etwas versteckt, es ist der temporäre Wert, den du beim Aufruf der Funktion benutzt. Der Logikfehler ist hier entweder, dass die Funktion den Wert nicht ändert (und daher den Parameter als const-Referenz nehmen sollte) oder dass die Funktion den Wert ändert und daher nicht mit einem temporären Wert aufgerufen werden kann. Da der Code deiner Funktion elend lang ist (auch so eine Sache, die man eher vermeiden sollte), habe ich nicht geguckt, welcher der beiden Fälle vorliegt. Aber schönerweise wird der Compiler dir einen anderen Fehler liefern, falls du nun ein falsches const setzt, insofern kannst du auch gar nichts falsch machen (außer du beschließt, ganz auf const, und damit auf die Logikkontrolle durch den Compiler, zu verzichten).

    Dementsprechend muss Matrix const sein? Und wieso heisst es im error non-const reference of type ‘std::vector<int>&’, da müsste doch die Matrix stehen. Das sieht aber eher so aus als wenn sich das auf neurons bezieht, was ja sicherlich nicht const ist.

    Der Compiler weiß schon, wovon er spricht. Versuch die Meldungen nicht um zu interpretieren. Pro-Tipp: Du benutzt offenbar den GCC (oder einen Compiler mit identischem Fehlermeldungsstil). Zu der gezeigten Fehlermeldung gehört bei dem auch noch eine weitere Zeile (die mit dem "^") in der er zeigt, auf welchen Teil des Codes sich die Meldung genau bezieht.


  • Mod

    cpp_Jungspund schrieb:

    Hi

    Danke für die Mühe. Unglaublich wie kurz du diesen Code bekommen hast. Ich werde mir den Code genau ansehen.

    Allerdings leider falsch. Hatte die Zuweisung

    basins[nNumber] = nattractor;
    

    weiter oben übersehen. Da ich ActivityToNumber nicht kenne, muss ich annehmen, dass dieses auch mal Werte größer als ncounter liefern kann, womit die Annahme, dass ncounter immer auf das letzte nicht-Null Element verweist, nicht zutreffen würde.

    So sollte es gehen:

    void int2bits_vector(int value, std::vector<int>& c) {
        for ( auto& i : c ) {
            i = value % 2;
            value /= 2;
        }
    }
    
    ...
    
        // Investigate attractors
        for ( ;; ) {
            std::vector<int> helpneurons = Update::Hebb( Matrix, neurons );
            neurons = TransferFunction::StepFunction( helpneurons );
    
            int nNumber = ActivityToNumber( neurons );
    
            if ( basins[nNumber] == 0 ) {
                basins[nNumber] = nattractor;
            }else{
                if ( basins[nNumber] == nattractor ) {
                    if ( nattractor > 100 ) {
                        print << "Warning: attractor > 100";
                        exit( EXIT_FAILURE );
                    }
                    ++nattractor;
                } else {
                    for ( int i = 0; i < Var._SampleSize; ++i ) {
                        if ( basins[i] == nattractor ) {
                            basins[i] = basins[nNumber];
                        }
                    }
                }
    
                while ( ( ncounter < Var._SampleSize ) && ( basins[ncounter] > 0 ) ) {
                    ++ncounter;
                }
    
                if ( ncounter == Var._SampleSize ) {
                    break;
                }
                basins[ncounter] = nattractor;
    
                int2bits_vector( ncounter, neurons );
            }
        }
    

    Der Code für int2bit_vector kommt öfter vor, lohnt also ausgelagert zu werden. Vermutlich kann man einen besseren Namen dafür finden.

    cpp_Jungspund schrieb:

    Wie ist dieser Fehler zu interpretieren? Sicher das ich nicht doch meine helpneurons benötige und das in zwei Schritte packen müsste?

    Attractor.cpp: In static member function ‘static void Attractor::AnalysisBinary(std::vector<std::vector<int> >&)’:
    Attractor.cpp:82:63: error: invalid initialization of non-const reference of type ‘std::vector<int>&’ from an rvalue of type ‘std::vector<int>’
             neurons = TransferFunction::StepFunction( Update::Hebb( Matrix, neurons ) );
    

    const-Korrektheit vermutlich nicht beachtet. Da neurons per Zuweisung geändert wird, habe ich angenommen, dass TransferFunction::StepFunction sein Argument nicht verändert. Sollte das doch der Fall sein, ist der Weg über die Zwischenvariable zweckmäßig.

    Übrigens sind _AdSize und _SampleSize reservierte Bezeichner, die nicht verwendet werden dürfen.



  • Hallo

    Ich habe meinen Code umgebaut, die while Schleifen heraus genommen, die If Abfragen verbessert, die Funktion (ich nannte sie NumberToActivity) eingebaut und erhalte nun von valgrind keinen Fehler mehr und das Programm liefert richtige Ergebnisse. Der Gesamtcode bei mir ist dadurch inzwischen viel lesentlicher als zuvor. Danke dafür 🙂

    Eines noch: Ich erhalte keinen Fehler mehr, dafür spuckt valgrind mir immer dieses hier als erstes aus. Irgendwas scheint ja doch noch nicht ganz richtig zu sein. Was bedeutet das?

    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/ld-2.22.so:
    --24813-- Ignoring non-Dwarf2/3/4 block in .debug_info
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/ld-2.22.so:
    --24813-- Last block truncated in .debug_info; ignoring
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/ld-2.22.so:
    --24813-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libm-2.22.so:
    --24813-- Ignoring non-Dwarf2/3/4 block in .debug_info
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libm-2.22.so:
    --24813-- Last block truncated in .debug_info; ignoring
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libm-2.22.so:
    --24813-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
    --24813-- Ignoring non-Dwarf2/3/4 block in .debug_info
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
    --24813-- Last block truncated in .debug_info; ignoring
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
    --24813-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
    

    camper schrieb:

    Übrigens sind _AdSize und _SampleSize reservierte Bezeichner, die nicht verwendet werden dürfen.

    Wieso denn dies? Wofür stehen denn diese Bezeichner?
    Ich habe gelernt, dass Membervariablen immer mit einem Tiefstrich beginnen sollen und CamelCase Notation haben sollten. Ist dem nicht so?

    Grüße



  • cpp_Jungspund schrieb:

    Wieso denn dies? Wofür stehen denn diese Bezeichner?
    Ich habe gelernt, dass Membervariablen immer mit einem Tiefstrich beginnen sollen und CamelCase Notation haben sollten. Ist dem nicht so?

    Microsoft führte den Stil m_camelCase ein. Da lauter Leute MS hassen, haben sie alternativ _camelCase und camelCase_ probiert.
    Ich habe entdeckt, daß die Namenkollissionen NUR in Konstruktoren passieren. Fertig. Man hat keine getter/setter. Außer in GUI-Klassen. Aber nicht in echtem Code.
    Ein Javaod hat mir mal gezeigt, daß

    class Foo{
        int _a;
        Foo(int a){
            _a=a;
        }
    };
    

    viel klarer ist mit

    class Foo{
        int a;
        Foo(int a){
            this->a=a;
        }
    };
    

    Jo, da hatter recht, oda? Naja, im Sinne von freundlich sein gegenüber neuen Mitarbeitern, die können den Code sofort verstehen, statt aich erst die unternehmenseigene (nichtexistente!!!) Doku duchlesen zu müssen.

    Irgendie auch wutzcool ist

    class Foo{
        int a;
        Foo(int a)
        :a(a){
        }
    };
    


  • Ich bin überrascht das an dieser Stelle nicht der Standard zitiert wird, sonst wird das doch immer gerne gemacht 🙂 [oder ist das in den neueren Standards rausgeflogen?]
    Hier mal ein Link, den ich mal zu diesem Thema erhalten habe: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797


  • Mod

    Ich habe entdeckt, daß die Namenkollissionen NUR in Konstruktoren passieren.

    struct B {
        protected: int T; // Na gut, leicht gekünstelt. Wer verwendet schon protected Variablen? Mit private wird es halt ein Compilerfehler, das ist 
                          // nach wie vor eine Kollision (aber nicht eine derart tückische!)
    };
    
    template <typename T>
    struct A : B {
        static const auto sizeofT = sizeof(T); // Aua
    };
    

    Lösung des Problems? Member und Template-Parameter (und Namen anderer Arten von Entitäten) unterschiedlich präfigieren. Bei Membern hau ich gern ein _ vor, außer sie sind public .



  • push 🙂

    cpp_Jungspund schrieb:

    Eines noch: Ich erhalte keinen Fehler mehr, dafür spuckt valgrind mir immer dieses hier als erstes aus. Irgendwas scheint ja doch noch nicht ganz richtig zu sein. Was bedeutet das?

    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/ld-2.22.so:
    --24813-- Ignoring non-Dwarf2/3/4 block in .debug_info
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/ld-2.22.so:
    --24813-- Last block truncated in .debug_info; ignoring
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/ld-2.22.so:
    --24813-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libm-2.22.so:
    --24813-- Ignoring non-Dwarf2/3/4 block in .debug_info
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libm-2.22.so:
    --24813-- Last block truncated in .debug_info; ignoring
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libm-2.22.so:
    --24813-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
    --24813-- Ignoring non-Dwarf2/3/4 block in .debug_info
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
    --24813-- Last block truncated in .debug_info; ignoring
    --24813-- WARNING: Serious error when reading debug info
    --24813-- When reading debug info from /lib/x86_64-linux-gnu/libc-2.22.so:
    --24813-- parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4
    

  • Mod

    Hast du dies hier mal probiert?


Anmelden zum Antworten