2017-07-23 5 views
-1
Layer::Layer(int LayerSize, Layer PrevLayer){ 

Size=LayerSize; 

Column=(Neuron*)malloc(Size); 

for(int i=0;i<Size;i++){ 


    Column[i]=Neuron(LayerSize,LayerSize,LayerSize); 

    Input[i]=&Column[i].Input;      //1 

    PrevLayer.Output[i]=Input[i];      //2 

} 

Ich versuche Input[i] Punkt auf den Eingang des entsprechenden Neurons zu haben. Während die Speicheradressen korrekt scheinen, stürzt das Programm ab, wenn ich versuche, den Adresswert der Elementvariablen Input in Zeile //1 zuzuweisen. Irgendeine Idee, was falsch ist, oder bessere Methoden, die ich verwenden könnte?Zuordnung einer Mitgliedsvariablenadresse zu einem Zeiger nicht möglich

Im Folgenden sind die Klassen mit den entsprechenden Mitgliedern

} 

class Neuron{ 

public: 

    Neuron(int PrevColumnSize, int ThisColumnSize, int NextColumnSize); 

          //Constructor: Generates a Neuron with random values 

    double Input;   //input of each neuron 


}; 


class Layer{ 

private: 

    int Size;    //Number of Neurons in the layer 

public: 

    Layer(int LayerSize); //Constructor; Layer with no attached layers; used at the start of a network 


    Layer(int LayerSize, Layer PrevLayer); 

          //Constructor; Layer which attaches itself to the next, and the previous layers; unused 

    Neuron* Column;   //Column of Neurons 

    double** Input;   //Inputs to Neurons 

}; 
+0

Mögliches Duplikat von [Ist nicht initialisierte lokale Variable der schnellste Zufallszahlengenerator?] (Https://stackoverflow.com/questions/31739792/is-uninitialized-local-variable-the-fastest-random-number-generator) – LogicStuff

+1

Off topic: 'Layer PrevLayer' ist pass-by-value. Alle Änderungen, die Sie an "PrevLayer" vornehmen, werden an einer Kopie vorgenommen und gehen am Ende dieser Funktion verloren, wenn 'PrevLayer' den Gültigkeitsbereich verlässt und zerstört wird. Dies wäre eine wirklich gute Zeit, um sich mit [Was ist die Regel von drei?] (Https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – user4581301

+0

Vielen Dank user4581301, I habe auch versucht, es als 'layer * PrevLayer' zu definieren und ihm eine Adresse zu übergeben, aber das hat auch nicht funktioniert – lordflashhart

Antwort

2

Es gibt mehrere Fehler im Code Verwirbelung und eine weiteren schwierigen eine der Fehler zu isolieren, um Fütterung aus. Es ist einfach, einen der Fehler zu beheben und es nicht zu bemerken, weil ein anderer Fehler sofort seinen Platz einnimmt.

Bugs 1 und 2 sind wahrscheinlich sofort fatal und was OP sieht, da sie mit dem Zugriff auf ungültigen Speicher zu tun haben. Column (Bug 1) wird nicht genügend Speicher zugewiesen und Input (Bug 2) wird keinen Speicher zugeordnet. Bug 3, PrevLayer Wert überschritten, ist ein Ärgernis, aber nicht sofort tödlich wegen Bug 4 (unzureichende destuctor Ergebnisse im Speicherverlust) negieren Bug 5 (Rule of Three Verletzung).

Wir werden mit Bug 3 beginnen, weil es zuerst im Code dargestellt wird, obwohl es danach gesehen wird. Plus, es ist eine sehr schnelle Lösung.

Layer::Layer(int LayerSize, Layer PrevLayer){ 

Bug 3 PrevLayer wird als Wert übergeben. Dadurch wird eine Kopie der Quelle Layer und aller Änderungen an PrevLayer in der Quelle Layer nicht angezeigt. Lösung: Als Referenz übergeben. Layer(int LayerSize, Layer & PrevLayer)

Size=LayerSize; 

Hier bug 1:

Column=(Neuron*)malloc(Size); 

malloc zuordnet Bytes, keine Objekte. Dies bringt Sie auf zwei Arten: 1. Neuron 's Konstruktor wird nicht ausgeführt, so dass Sie Neuron s nicht initialisiert haben. 2. Sie haben Size Bytes, nicht SizeNeuron s. Neuron Die Größe ist größer als ein Byte, Sie haben also nicht genügend Speicher zugewiesen.

Lösung: Verwenden Sie std::vector<Neuron> Column; Dies ist schließlich C++, also gibt es keine Notwendigkeit, Speicher wie in einem C-Programm zu reservieren.

Bug 2 muss auch hier angesprochen werden. Für Input wurde kein Speicher reserviert. Lösung: std::vector<double*>; Aber Achtung: Dies bringt Ihnen nicht viele Vorteile in Bezug auf Geschwindigkeit auf einem modernen Prozessor und ermöglicht die Möglichkeit, dass die Zeiger aufgrund einer Größenänderung von Column ungültig gemacht werden können. Sie sind viel besser dran, nur den Wert von Column wie erforderlich zu bekommen. Bereits durch die Verwendung std::vector gelöst Bugs 1 und 2.

Ordnung zu lösen:

for(int i=0;i<Size;i++){ 
     Column[i]=Neuron(LayerSize,LayerSize,LayerSize); 

Bug 2 wird hier

 Input[i]=&Column[i].Input;      //1 
     PrevLayer.Output[i]=Input[i];      //2 
    } 
} 

Bugs 3, 4 und 5 freigelegt werden. Wie stellen wir all diese Lösungen zusammen?

class Neuron{ 
public: 
    Neuron(int PrevColumnSize, int ThisColumnSize, int NextColumnSize); 
    double Input;   //input of each neuron 
}; 


class Layer{ 
    // Size is gone. vector knows how big it its. 
    std::vector <Neuron> Column; //Column of Neurons 
    std::vector <double*> Output; // really bad idea. Strongly recommend a rethink 
public: 
    Layer(int LayerSize); 
    Layer(int LayerSize, Layer &PrevLayer); // now takes a reference 
    double operator[](size_t index) // to safely access Input. 
    { 
     return Column[index].Input; 
    } 
}; 

Layer::Layer(int LayerSize, Layer &PrevLayer){ 
    for(int i=0;i<LayerSize;i++){ 
     Column.emplace_back(LayerSize,LayerSize,LayerSize); 
    } 
    // these steps must be separated and Column must never change size or 
    // these pointers are toast 
    for (Neuron & column: Column) 
    { 
     PrevLayer.Output[i]=&column.Input; // This has a lot of potential for failure 
              // Strongly recommend a rethink 
    } 
} 

Die Rule of Three und alle Zerstörung Logik von std::vector

Documentation on std::vector

Jetzt behandelt wird, dass ich das alles aus heftig geschlagen habe, frage ich mich, die Notwendigkeit einer Neuron Klasse. Ein vector Double und eine Funktion zur Berechnung der Eingabe ist alles, was erforderlich scheint.

Verwandte Themen