Uninitialised value was created by a stack allocation



  • Hallo

    Mein Pogramm ist fertig und wird auch ohne Warnungen kompiliert und liefet bei Ausführug auch korrekte Ergebnisse.

    Wenn ich es jedoch mit valgrind --leak-check=full aufrufe erhalte ich einen Fehler das eine Initialisierung falsch läuft. Mittels valgrind --track-origins=yes bekomme ich folgende Meldung:

    ==5729== Conditional jump or move depends on uninitialised value(s)
    ==5729==    at 0x403A25: Attractor::AnalysisBinary(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) (Attractor.cpp:99)
    ==5729==    by 0x4060FB: main (HopfieldMain.cpp:63)
    ==5729==  Uninitialised value was created by a stack allocation
    ==5729==    at 0x40357A: Attractor::AnalysisBinary(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) (Attractor.cpp:41)
    

    In Attractor.cpp:99 findet sich

    while(basins[ncounter]>0){ // Zeile 99
       ncounter=ncounter+1;
       k=k+1;}
    

    und in Attractor.cpp:41 wo die uninitialisierte stack Allokation auftreten soll befindet sich

    int basins[Var._SampleSize]; // Zeile 41
    

    Dieses Array initialisiere ich aber mit

    for(i=0; i<Var._SampleSize; ++i){basins[i]=0;} // Zeile 54
    

    Die Methode AnalysisBinary wird im Header Attractor.h deklariert:

    static void AnalysisBinary(std::vector< std::vector<int> > & Matrix); // Analysis of the attractor landscape in binary encoding
    

    Dabei wird eine Matrix via call by reference übergeben, welche ich zuvor berechnen lasse.

    Kann mir bitte jemand sagen was ich falsch mache? Ich poste hier mal den Code der ganzen Methode:

    // Analysis for the attractor landscape in binary encoding
    void Attractor::AnalysisBinary(std::vector< std::vector<int> > & Matrix){
    std::ofstream print("./Output.txt",std::ios_base::app);
    std::ofstream print2R_SizeOfBasins("./SizeOfBasins.txt",std::ios_base::out);   
    std::ofstream print2R_DotProductAttractorsAdjointCSpace("./DotProductAttractorsAdjointCSpace.txt",std::ios_base::out);   
    
    // Declare attractor analysis
    Network Net;
    Network Var;
    TransferFunction Value;
    
    int basins[Var._SampleSize];
    std::vector< std::vector<int> > attractor(100, std::vector<int>(52));
    std::vector<int> neurons(Net._AdSize);
    std::vector<int> helpneurons(Net._AdSize);
    
    int ncounter;
    int nattractor;
    int ntest;
    int ih1, ih2, ih3, i_att;
    int nNumber;
    int i, j, k;
    
    // Initialize attractor counter
    for(i=0; i<Var._SampleSize; ++i){basins[i]=0;}
    
    for(i=0; i<100; ++i){
       for(j=0; j<52; ++j){
       attractor[i][j]=0;
       }
    }
    
    neurons = {0};
    ncounter=0;
    nattractor=1;
    basins[0]=1;
    
    // Investigate attractors 
    while(ncounter<Var._SampleSize){
    helpneurons = {0};
    helpneurons = Update::Hebb(Matrix, neurons); // Update
    neurons = TransferFunction::StepFunction(helpneurons); //Activation function
    
    nNumber=0;
    nNumber=ActivityToNumber(neurons); // Neural activity to number
    
    if(basins[nNumber]==0){basins[nNumber]=nattractor;}
    
    else{if(basins[nNumber]==nattractor)
    {
    
       if(nattractor>100){
       print << "Warning: attractor > 100";
       exit(EXIT_FAILURE);}
    
       nattractor=nattractor+1;
       while(basins[ncounter]>0){ncounter=ncounter+1;}
       ih1=ncounter;
       basins[ncounter]=nattractor;
       for(i=0;i<Net._AdSize;++i){neurons[i]=ih1%2; ih1=(ih1-neurons[i])/2;} // Number to neural activity
    }
    
    else{
       k=0;
       for(i=0; i<Var._SampleSize; ++i){
       if(basins[i]==nattractor){
       k=k+1;
       basins[i]=basins[nNumber];}}
    
       while(basins[ncounter]>0){
       ncounter=ncounter+1;
       k=k+1;}
    
       basins[ncounter]=nattractor;
    
       ih1=ncounter;
    
       for(i=0;i<Net._AdSize;++i){neurons[i]=ih1%2; ih1=(ih1-neurons[i])/2;}
      }
     }
    }
    
    for(i=0; i<Var._SampleSize; ++i){attractor[basins[i]][50]=attractor[basins[i]][50]+1;}
    
    for(i_att=1;i_att<nattractor;++i_att){
       ih1=0;
    
       while(basins[ih1]!=i_att){ih1=ih1+1;}
    
       for(j=0;j<Net._AdSize;++j){neurons[j]=ih1%2; ih1=(ih1-neurons[j])/2;}
    
    //Update neural activity 70 times
    for(k=0; k<70; ++k){
    helpneurons = {0};
    helpneurons = Update::Hebb(Matrix, neurons); // Update
    neurons = TransferFunction::StepFunction(helpneurons); // Activation function
    }
    
    nNumber=0;
    nNumber=ActivityToNumber(neurons); // Neural activity to number
    
    ntest=0;
    ih2=-1;
    ih3=nNumber;
    
    while(nNumber!=ih2)
    {
    ntest=ntest+1;
    attractor[i_att][ntest]=ih3;
    
    helpneurons = {0};
    helpneurons = Update::Hebb(Matrix, neurons); // Update
    neurons = TransferFunction::StepFunction(helpneurons); // Activation function
    
    ih3=0;
    ih3=ActivityToNumber(neurons); // Neural activity to number
    ih2=ih3;
    }
    
    attractor[i_att][51]=ntest;
    if(ntest>50){
    print << "Warning: size of attractor > 50";
    exit(EXIT_FAILURE);}
    }  
    
    // Print first results of the attractor analysis
    print << "\nResults of the attractor analysis:" << "\n";
    print << "\nNumber of basins: " << (nattractor-1) << "\n";
    
    for(i=1;i<nattractor;++i){
       print << "\nAttractor: " << i;
       print << "\nSize of the basin: " << attractor[i][50];
       print << "\nNumber of states: " << attractor[i][51] << "\n";
    
       for(j=1;j<(attractor[i][51]+1);++j){
            //print  << "Binary exponentiation: " << attractor[i][j];
            print  << "\nNeural Activity: ";
            ih1=attractor[i][j];
            for(k=0; k<Net._AdSize; ++k){neurons[k]=ih1%2; ih1=(ih1-neurons[k])/2;}
              for(k=0; k<Net._AdSize; ++k)
              {
              print << neurons[k] << " ";
              }
           print << "\n";
       }  
    }  
    
    // Print the size of the basins 
    print2R_SizeOfBasins << "#Size of the basins" << "\n";
    for(i=0; i<nattractor-1; ++i){print2R_SizeOfBasins << attractor[i][50] << "\n";}
    
    // Store attractors in a matrix 
    std::vector< std::vector<int> > Attractors(nattractor-1, std::vector<int>(Net._AdSize));
    
    for(i=1;i<nattractor;++i)
    {
        for(j=1;j<(attractor[i][51]+1);++j)
        {
        ih1=attractor[i][j];
        for(k=0; k<Net._AdSize; ++k){Attractors[i-1][k]=ih1%2; ih1=(ih1-Attractors[i-1][k])/2;}         
        }  
    }  
    
    // Initialize configuration space
    std::vector< std::vector<int> > CSpace(Var._SampleSize, std::vector<int>(Net._AdSize +1));
    int ipattern;
    for(i=0; i<Var._SampleSize; i++)
    {
      for(j=0; j<Net._AdSize+1; j++)
      {
      CSpace[i][j] = 0;
      }
    }
    
    // Set configuration space
    for(ipattern=0; ipattern<Var._SampleSize; ++ipattern)
    {
    j=ipattern; k=0; 
    for (i=1; i<Net._AdSize; i++) {CSpace[ipattern][i+1]=0;}       
       while(j>0) // Set Pattern from ipattern
       {                  
       CSpace[ipattern][k+1]=j%2;
       j=(j-j%2)/2;
       k=k+1;
       }
    }
    
    // Append attractor counter to the configuration space. First Column correspond to the attractor
    std::vector<int> AttrCount(Var._SampleSize);
    for(i=0; i<Var._SampleSize; i++){AttrCount[i]=basins[i];}
    
    for(i=0; i<Var._SampleSize; ++i)
    {
    int AttrIndex = AttrCount[i];  
    CSpace[i][0]=AttrIndex;    
    }
    
    // Print configurationspace. 
    print << "\n#Attractor-No.  State vector" << "\n";
    for(const std::vector<int> &i: CSpace){
      for(int j: i){print << j << ' ';}
    print << "\n";
    }
    
    // Calculate inner products < attractors | adjoint state vectors>
    // Initialize matrix DotProductAttractorsAdjointCSpace
    std::vector< std::vector<int> > DotProductAttractorsAdjointCSpace(nattractor-1, std::vector<int>(Var._SampleSize));
    std::vector<int> vectorA(Net._AdSize);
    std::vector<int> vectorB(Net._AdSize);
    std::vector<int> index(nattractor-1);
    
    for( int y = 0; y < Var._SampleSize; y++)
    {    
        for(i=0; i<Net._AdSize; ++i){
        vectorA[i] = Attractors[CSpace[y][0]-1 ][i];
        }
    
        for( int x = 1; x < nattractor; x++){
        vectorB[x -1] = CSpace[y][x];
        }
    
        DotProductAttractorsAdjointCSpace[ CSpace[y][0] -1][index[ CSpace[y][0] -1] ] = inner_product(vectorA.begin(), vectorA.end(), vectorB.begin(), 0); // Calculate inner product
    
        index[CSpace[y][0]-1] += 1;
    }
    
    // Print DotProductAttractorsAdjointCSpace
    print2R_DotProductAttractorsAdjointCSpace << "#DotProductAttractorsAdjointCSpace" << "\n";
     for ( const std::vector<int> &i : DotProductAttractorsAdjointCSpace ){
        for ( int j : i ) print2R_DotProductAttractorsAdjointCSpace << j << ' ';
        print2R_DotProductAttractorsAdjointCSpace << "\n";
     }
    
    }
    

    Die Objekte net und Var befinden sich in einer Klasse Network und wurden darin von mir in dessen Konstruktor zu 4 und 16 deklariert:

    // Constructor for the Network class.
    Network::Network() {
    _AdSize = 4; 
    _SampleSize=std::pow(2,_AdSize);
    }
    

    Danke für Hilfe und Grüße


  • Mod

    Anscheinend ist basins ein VLA. Warum kein vector<int> , wo du doch gleich danach welche deklarierst? Womöglich kann Valgrind mit VLAs nicht richtig umgehen. Was ist der Wert von Var._SampleSize ?

    Im Übrigen kannst du das Array einfach so initialisieren:

    int basins[Var._SampleSize] = {};
    


  • Hallo

    Ursprünglich hatte ich basins als Vektor definiert. Wenn ich dies mache läuft das Programm ebenfalls korrekt ohne Fehler durch, jedoch liefert mit valgrind dann folgende Fehlermeldungen:

    ==7245== Invalid read of size 4
    ==7245==    at 0x403A85: Attractor::AnalysisBinary(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) (Attractor.cpp:99)
    ==7245==    by 0x4061D5: main (HopfieldMain.cpp:63)
    ==7245==  Address 0x5a8b550 is 0 bytes after a block of size 256 alloc'd
    ==7245==    at 0x4C2A16F: operator new(unsigned long) (vg_replace_malloc.c:333)
    ==7245==    by 0x40232D: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)
    ==7245==    by 0x4020A8: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:491)
    ==7245==    by 0x401E7B: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)
    ==7245==    by 0x401B98: std::_Vector_base<int, std::allocator<int> >::_M_create_storage(unsigned long) (stl_vector.h:185)
    ==7245==    by 0x4017F2: std::_Vector_base<int, std::allocator<int> >::_Vector_base(unsigned long, std::allocator<int> const&) (stl_vector.h:136)
    ==7245==    by 0x40152D: std::vector<int, std::allocator<int> >::vector(unsigned long, std::allocator<int> const&) (stl_vector.h:278)
    ==7245==    by 0x4035A0: Attractor::AnalysisBinary(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) (Attractor.cpp:41)
    ==7245==    by 0x4061D5: main (HopfieldMain.cpp:63)
    ==7245== 
    ==7245== Invalid write of size 4
    ==7245==    at 0x403AB8: Attractor::AnalysisBinary(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) (Attractor.cpp:103)
    ==7245==    by 0x4061D5: main (HopfieldMain.cpp:63)
    ==7245==  Address 0x5a8b550 is 0 bytes after a block of size 256 alloc'd
    ==7245==    at 0x4C2A16F: operator new(unsigned long) (vg_replace_malloc.c:333)
    ==7245==    by 0x40232D: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)
    ==7245==    by 0x4020A8: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:491)
    ==7245==    by 0x401E7B: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)
    ==7245==    by 0x401B98: std::_Vector_base<int, std::allocator<int> >::_M_create_storage(unsigned long) (stl_vector.h:185)
    ==7245==    by 0x4017F2: std::_Vector_base<int, std::allocator<int> >::_Vector_base(unsigned long, std::allocator<int> const&) (stl_vector.h:136)
    ==7245==    by 0x40152D: std::vector<int, std::allocator<int> >::vector(unsigned long, std::allocator<int> const&) (stl_vector.h:278)
    ==7245==    by 0x4035A0: Attractor::AnalysisBinary(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) (Attractor.cpp:41)
    ==7245==    by 0x4061D5: main (HopfieldMain.cpp:63)
    

    Der genannte Code:

    while(basins[ncounter]>0){  // Attractor.cpp:99
       ncounter=ncounter+1;
       k=k+1;}
    
    std::vector<int> basins(Var._SampleSize); // Attractor.cpp:41
    
    basins[ncounter]=nattractor; // Attractor.cpp:103
    

    Ich weiss nicht was da los ist.

    Var._SampleSize wird in meiner Netzwerk Kasse so definiert:

    // Constructor for the Network class.
    Network::Network() {
    _AdSize = 4;
    _SampleSize=std::pow(2,_AdSize);
    }
    

    Gruß


  • Mod

    while(basins[ncounter]>0){
       ncounter=ncounter+1;
       k=k+1;}
    

    Was hindert ncounter in dieser Schleife daran, zu groß zu werden?



  • Hi

    Nur die Abbruchbedingung hindert den Zähler groß zu werden. Die while Schleife wird ja nur solange ausgeführt bis der darin definierte Ausdruck nicht mehr wahr ist.

    Aber wieso bekomme ich diese Fehlermeldungen?


  • Mod

    cpp_Jungspund schrieb:

    Nur die Abbruchbedingung hindert den Zähler groß zu werden. Die while Schleife wird ja nur solange ausgeführt bis der darin definierte Ausdruck nicht mehr wahr ist.

    Wie ist denn garantiert, dass die Bedingung jemals wahr wird?


  • Mod

    Ich habe mal ein bisschen formatiert und unnötig vorab definierte Variablen dahin verschoeben, wo sie gebraucht werden.

    // Analysis for the attractor landscape in binary encoding
    void Attractor::AnalysisBinary(std::vector< std::vector<int> > & Matrix){
        std::ofstream print("./Output.txt",std::ios_base::app);
        std::ofstream print2R_SizeOfBasins("./SizeOfBasins.txt",std::ios_base::out);  
        std::ofstream print2R_DotProductAttractorsAdjointCSpace("./DotProductAttractorsAdjointCSpace.txt",std::ios_base::out);  
    
        // Declare attractor analysis
        Network Net;
        Network Var;
        TransferFunction Value; // unused?
    
        std::unique_ptr<int[]> basins(new int[Var._SampleSize]{1});
        std::vector<int> neurons(Net._AdSize);
    
        int ncounter=0;
        int nattractor=1;
    
        // Investigate attractors
        while(ncounter<Var._SampleSize){
            std::vector<int> helpneurons = Update::Hebb(Matrix, neurons); // Update
            neurons = TransferFunction::StepFunction(helpneurons); //Activation function
    
            int nNumber=ActivityToNumber(neurons); // Neural activity to number
    
            if(basins[nNumber]==0){
                basins[nNumber]=nattractor;
            }else{
                if(basins[nNumber]==nattractor){
                    if(nattractor>100){
                        print << "Warning: attractor > 100";
                        exit(EXIT_FAILURE);
                    }
                    nattractor=nattractor+1;
                    while(basins[ncounter]>0){
                        ncounter=ncounter+1;
                    }
                    int ih1=ncounter;
                    basins[ncounter]=nattractor;
                    for(int i=0;i<Net._AdSize;++i){
                        neurons[i]=ih1%2;
                        ih1=(ih1-neurons[i])/2;
                    } // Number to neural activity
                }else{
                    for(int i=0; i<Var._SampleSize; ++i){
                        if(basins[i]==nattractor){
                            basins[i]=basins[nNumber];
                        }
                    }
    
                    while(basins[ncounter]>0){
                        ncounter=ncounter+1;
                    }
    
                    basins[ncounter]=nattractor;
    
                    int ih1=ncounter;
    
                    for(int i=0;i<Net._AdSize;++i){
                        neurons[i]=ih1%2;
                        ih1=(ih1-neurons[i])/2;
                    }
                }
            }
        }
    
        std::vector< std::vector<int> > attractor(100, std::vector<int>(52));
        for(int i=0; i<Var._SampleSize; ++i){
            attractor[basins[i]][50]=attractor[basins[i]][50]+1;
        }
    
        for(int i_att=1;i_att<nattractor;++i_att){
            int ih1=0;
            while(basins[ih1]!=i_att){
                ih1=ih1+1;
            }
            for(int j=0;j<Net._AdSize;++j){
                neurons[j]=ih1%2;
                ih1=(ih1-neurons[j])/2;
            }
    
            //Update neural activity 70 times
            for(int k=0; k<70; ++k){
                std::vector<int> helpneurons = Update::Hebb(Matrix, neurons); // Update
                neurons = TransferFunction::StepFunction(helpneurons); // Activation function
            }
    
            int nNumber=ActivityToNumber(neurons); // Neural activity to number
    
            int ntest=0;
            int ih2=-1;
            int ih3=nNumber;
    
            while(nNumber!=ih2){
                ntest=ntest+1;
                attractor[i_att][ntest]=ih3;
    
                std::vector<int> helpneurons = Update::Hebb(Matrix, neurons); // Update
                neurons = TransferFunction::StepFunction(helpneurons); // Activation function
    
                ih3=ActivityToNumber(neurons); // Neural activity to number
                ih2=ih3;
            }
    
            attractor[i_att][51]=ntest;
            if(ntest>50){
                print << "Warning: size of attractor > 50";
                exit(EXIT_FAILURE);}
            }  
    
            // Print first results of the attractor analysis
            print << "\nResults of the attractor analysis:" << "\n";
            print << "\nNumber of basins: " << (nattractor-1) << "\n";
    
            for(int i=1;i<nattractor;++i){
                print << "\nAttractor: " << i;
                print << "\nSize of the basin: " << attractor[i][50];
                print << "\nNumber of states: " << attractor[i][51] << "\n";
    
                for(int j=1;j<(attractor[i][51]+1);++j){
                    //print  << "Binary exponentiation: " << attractor[i][j];
                    print  << "\nNeural Activity: ";
                    ih1=attractor[i][j];
                    for(int k=0; k<Net._AdSize; ++k){
                        neurons[k]=ih1%2;
                        ih1=(ih1-neurons[k])/2;
                    }
                    for(int k=0; k<Net._AdSize; ++k){
                        print << neurons[k] << " ";
                    }
                    print << "\n";
                }
            }
    
            // Print the size of the basins
            print2R_SizeOfBasins << "#Size of the basins" << "\n";
            for(int i=0; i<nattractor-1; ++i){
                print2R_SizeOfBasins << attractor[i][50] << "\n";
            }
    
            // Store attractors in a matrix
            std::vector< std::vector<int> > Attractors(nattractor-1, std::vector<int>(Net._AdSize));
    
            for(int i=1;i<nattractor;++i){
                for(int j=1;j<(attractor[i][51]+1);++j){
                    ih1=attractor[i][j];
                    for(int k=0; k<Net._AdSize; ++k){
                        Attractors[i-1][k]=ih1%2;
                        ih1=(ih1-Attractors[i-1][k])/2;
                    }
                }
            }
    
            // Initialize configuration space
            std::vector< std::vector<int> > CSpace(Var._SampleSize, std::vector<int>(Net._AdSize +1));
            int ipattern;
            for(int i=0; i<Var._SampleSize; i++){
                for(int j=0; j<Net._AdSize+1; j++){
                    CSpace[i][j] = 0;
                }
            }
    
            // Set configuration space
            for(ipattern=0; ipattern<Var._SampleSize; ++ipattern){
                int j=ipattern;
                int k=0;
                for (int i=1; i<Net._AdSize; i++){
                    CSpace[ipattern][i+1]=0;
                }
                while(j>0){ // Set Pattern from ipattern
                    CSpace[ipattern][k+1]=j%2;
                    j=(j-j%2)/2;
                    k=k+1;
                }
            }
    
            // Append attractor counter to the configuration space. First Column correspond to the attractor
            std::vector<int> AttrCount(Var._SampleSize);
            for(int i=0; i<Var._SampleSize; i++){
                AttrCount[i]=basins[i];
            }
    
            for(int i=0; i<Var._SampleSize; ++i){
                int AttrIndex = AttrCount[i];  
                CSpace[i][0]=AttrIndex;    
            }
    
            // Print configurationspace.
            print << "\n#Attractor-No.  State vector" << "\n";
            for(const std::vector<int> &i: CSpace){
                for(int j: i){
                    print << j << ' ';
                }
                print << "\n";
            }
    
            // Calculate inner products < attractors | adjoint state vectors>
            // Initialize matrix DotProductAttractorsAdjointCSpace
            std::vector< std::vector<int> > DotProductAttractorsAdjointCSpace(nattractor-1, std::vector<int>(Var._SampleSize));
            std::vector<int> vectorA(Net._AdSize);
            std::vector<int> vectorB(Net._AdSize);
            std::vector<int> index(nattractor-1);
    
            for( int y = 0; y < Var._SampleSize; y++){
                for( int i=0; i<Net._AdSize; ++i){
                   vectorA[i] = Attractors[CSpace[y][0]-1 ][i];
                }
    
                for( int x = 1; x < nattractor; x++){
                    vectorB[x -1] = CSpace[y][x];
                }
    
                DotProductAttractorsAdjointCSpace[ CSpace[y][0] -1][index[ CSpace[y][0] -1] ] = inner_product(vectorA.begin(), vectorA.end(), vectorB.begin(), 0); // Calculate inner product
    
                index[CSpace[y][0]-1] += 1;
            }
    
            // Print DotProductAttractorsAdjointCSpace
            print2R_DotProductAttractorsAdjointCSpace << "#DotProductAttractorsAdjointCSpace" << "\n";
            for ( const std::vector<int> &i : DotProductAttractorsAdjointCSpace ){
                for ( int j : i ){
                    print2R_DotProductAttractorsAdjointCSpace << j << ' ';
                }
                print2R_DotProductAttractorsAdjointCSpace << "\n";
            }
        }
    

    Man erkennt schnell, dass das Programm immer (mindestens) eine Position hinter das Array schreibt (entweder Zeile 38 oder Zeile 54), weil ncounter unmittelbar unmittelbar zuvor inkrementiert wird, und die While-Schleife (Zeile 19) nicht vorher abbrechen kann.



  • Danke für deine Mühe.

    Nach einer Weile drauf starren und deiner Erklärung sehe ich das Problem.

    Was wäre die einfachste Möglichkeit dies zu beheben? Vielleicht eine if Schleife einbauen welche aus der Schleife springt wenn ncounter bei SampleSize ist?

    Gruß





  • 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


Log in to reply