简体   繁体   中英

Can't assign an member variable address to a pointer

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

}

I'm trying to have Input[i] point to the input of the corresponding neuron. While the memory addresses seem correct, when I try to assign the address value of the member variable Input at line //1 , the program crashes. Any idea what's wrong, or better methods that I could use?

Below are the classes with the relevant members

}

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

};

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM