There are several bugs in the code intermingling and feeding off one another to make isolating any one of the bugs difficult. It's easy to fix one of the bugs and not notice it because another bug promptly takes its place.
Bugs 1 and 2 are likely immediately fatal and what OP is seeing as they have to do with accessing invalid memory. Column
(bug 1) is not being allocated enough storage and Input
(bug 2) is not being allocated any storage. Bug 3, PrevLayer
passed by value, is a nuisance, but not immediately fatal due to bug 4 (inadequate destuctor results in memory leak) negating bug 5 (Rule of Three violation).
We'll start with bug 3 because it is represented in the code first even though it will be seen after. Plus it's a really quick fix.
Layer::Layer(int LayerSize, Layer PrevLayer){
Bug 3 is PrevLayer
is passed by value. This makes a copy of the source Layer
and any modifications to PrevLayer
will not be seen in the source Layer
. Solution: Pass by reference. Layer(int LayerSize, Layer & PrevLayer)
Size=LayerSize;
Here is bug 1:
Column=(Neuron*)malloc(Size);
malloc
allocates bytes, not objects. This gets you two ways: 1. Neuron
's constructor is not run, so you have uninitialized Neuron
s. 2. You have Size
bytes, not Size
Neuron
s. Neuron
's size is greater than a byte, so you haven't allocated enough memory.
Solution: Use std::vector<Neuron> Column;
This is C++ after all, so there's no need to allocate memory like you would in a C program.
Bug 2 needs to be addressed right around here as well. No storage has been allocated for Input
. Solution: std::vector<double*>;
But note: this doesn't do you many favours with respect to speed on a modern processor and allows the possibility that the pointers can be rendered invalid due to a change in the size of Column
. You are much better off just getting the value from Column
as required.
for(int i=0;i<Size;i++){
Column[i]=Neuron(LayerSize,LayerSize,LayerSize);
Bug 2 will be exposed here
Input[i]=&Column[i].Input; //1
PrevLayer.Output[i]=Input[i]; //2
}
}
Bugs 3, 4 and 5: Already solved by using std::vector
to solve bugs 1 and 2.
Alright. So how do we put all these solutions together?
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
}
}
The Rule of Three and all destruction logic is handled by std::vector
Documentation on std::vector
Now that I've bashed all this out, I question the need for a Neuron
class. A vector
of double and a function to calculate input is all that appears to be required.