2017-07-23 4 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 

} 

J'essaie d'afficher Input[i] à l'entrée du neurone correspondant. Alors que les adresses de la mémoire semblent correctes, lorsque j'essaie d'affecter la valeur d'adresse de la variable membre Entrée à la ligne //1, le programme se bloque. Une idée de ce qui ne va pas, ou de meilleures méthodes que je pourrais utiliser?Impossible d'affecter une adresse de variable membre à un pointeur

Voici les classes avec les membres concernés

} 

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

Copie possible de [La variable locale non initialisée est-elle le générateur de nombres aléatoires le plus rapide?] (Https://stackoverflow.com/questions/31739792/is-ininitialized-local-variable-the-fastest-random-number-generator) – LogicStuff

+1

Hors sujet: 'Layer PrevLayer' est passé par valeur. Toutes les modifications que vous apportez à 'PrevLayer' sont faites à une copie et seront perdues à la fin de cette fonction quand' PrevLayer' sort de la portée et est détruit. Ce serait un très bon moment pour vous familiariser avec [Quelle est la règle de trois?] (Https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – user4581301

+0

Merci user4581301, je J'ai aussi essayé de le définir comme 'layer * PrevLayer', et de lui passer une adresse, mais cela ne fonctionnait pas non plus – lordflashhart

Répondre

2

Il y a plusieurs bugs dans le code entremêlés et se nourrissant les uns des autres pour faire isoler l'une des bogues difficiles. Il est facile de corriger l'un des bugs et de ne pas le remarquer car un autre bogue prend rapidement sa place.

Les bugs 1 et 2 sont probablement immédiatement fatals et ce que OP voit comme ils ont à voir avec l'accès à la mémoire invalide. Column (bug 1) n'est pas alloué suffisamment de stockage et Input (bug 2) ne se voit allouer aucun stockage. Le bogue 3, PrevLayer passé par valeur, est une nuisance, mais pas immédiatement mortel en raison du bogue 4 (résultat insuffisant de l'extracteur dans la fuite de mémoire) nociant le bug 5 (violation Rule of Three).

Commençons par le bogue 3 car il est représenté en premier dans le code même s'il sera vu après. De plus, c'est une solution très rapide.

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

Bug 3 est PrevLayer est passé par valeur. Cela fait une copie de la source Layer et aucune modification à PrevLayer ne sera pas vu dans la source Layer. Solution: Passer par référence. Layer(int LayerSize, Layer & PrevLayer)

Size=LayerSize; 

Voici bug 1:

Column=(Neuron*)malloc(Size); 

malloc octets, alloue pas des objets. Cela vous permet de deux manières: 1. Le constructeur de Neuron n'est pas exécuté, vous avez donc Neuron non initialisé. 2. Vous avez Size octets, pas SizeNeuron s. La taille de Neuron est supérieure à un octet. Vous n'avez donc pas alloué suffisamment de mémoire.

Solution: Utilisez std::vector<Neuron> Column; C++ est après tout, il n'est donc pas nécessaire d'allouer de la mémoire comme vous le feriez dans un programme C.

Le bogue 2 doit également être traité ici. Aucun stockage n'a été alloué pour Input. Solution: std::vector<double*>; Mais note: cela ne vous fait pas beaucoup de faveurs en ce qui concerne la vitesse sur un processeur moderne et permet la possibilité que les pointeurs peuvent être rendus invalides en raison d'un changement de la taille de Column. Il vaut mieux simplement obtenir la valeur de Column au besoin.

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

Bug 2 sera exposé ici

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

Bugs 3, 4 et 5: déjà résolu en utilisant std::vector pour résoudre les bugs 1 et 2.

D'accord. Alors, comment pouvons-nous mettre toutes ces solutions ensemble?

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 
    } 
} 

La règle de trois et toute logique de destruction est assurée par std::vector

Documentation on std::vector

Maintenant que je l'ai défoncé tout cela, je remets en question la nécessité d'une classe Neuron. Un vector de double et une fonction pour calculer l'entrée est tout ce qui semble être nécessaire.