Kelly Elton
Kelly Elton

Reputation: 4427

c++ dynamic arrays and pointers

Ok so what I'm trying to do is create an array of pointers that point to vectors that change in size. Also the array of pointers is nestled inside a class that's inside a vector. For some reason I seem to be having problems with memory becoming corrupt. Also if I use vectors I run into the problems with the stack overflowing caused by stuff resizing and calling constructors. Here is an essential layout of what I'm gunning for.

Diagram

Maybe a little sloppy. But I end up with the problem of memory being currupted in the babyclasses pointers, basically I want to access "linked" babyclasses via the babyclasses vector of babyclasses it's connected to. Any clever ideas here?

And before anyone tells me this is a silly way to do things, isn't this type of functionality the basis of OO Programming?

class Baby
{
public:
    deque<shared_ptr<Baby>> vInputs;
    int X;
    int Y;
    int Z;
    Baby()
    {
        numInputs = 0;
        isNull = false;
        wasTickled = false;
        X,Y,Z = 0;

    }
    void addInput(shared_ptr<Baby> baby)
    {
        if(numInputs == 0)
            vInputs = deque<shared_ptr<Baby>>(0);
        vInputs.push_back(baby);
        numInputs++;
    }
    void setXYZ(int x, int y, int z)
    {
        X = x;
        Y = y;
        Z = z;
    }
    void Tickle()
    {
        if(!wasTickled)
            wasTickled = true;
        else
            return;
        for(int i=0;i<numInputs;i++)
        {
            vInputs[i]->Tickle();
        }
    }
    void setNull(bool isnull)
    {
        isNull = isnull;
    }
private:
    int numInputs;
    bool isNull;
    bool wasTickled;
};
class BabyLayer
{
public:
    int Width;
    int Height;
    BabyLayer()
    {
        Width = 0;
        Height = 0;
    }
    BabyLayer(int width, int height)
    {
        Width = width;
        Height = height;
        vecBabies = std::deque<deque<Baby>>(0);
        for(int i=0;i<height;i++)
        {
            deque<Baby> row = deque<Baby>(0);
            for(int i=0;i<width;i++)
            {
                row.push_back(Baby());
            };
            vecBabies.push_back(row);
        }
        MakeConnections();
    }

    Baby * getBaby(int x, int y)
    {
        Baby n = Baby();
        n.setNull(true);
        if(x >= Width || x <0)
            return &n;
        if(y >= Height || y < 0)
            return &n;
        n.setNull(false);
        return &vecBabies[y][x];
    }
    ~BabyLayer(void)
    {

    }
private:
    std::deque<deque<Baby>> vecBabies;
    void MakeConnections()
    {
        for(int y=0;y<Height;y++)
        {
            for(int x=0;x<Width;x++)
            {
                //Top Right
                if(y > 0 && x < Width-1)
                    vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y-1][x+1]));
                //Middle Right
                if(x < Width -1)
                    vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y][x+1]));
                //Bottom Right
                if(x < Width -1 && y < Height-1)
                    vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y+1][x+1]));
                //Bottom Middle
                if(y < Height-1)
                    vecBabies[y][x].addInput(shared_ptr<Baby>(&vecBabies[y+1][x]));
            }
        }
    }
};
class BabyCube
{
public:
    int X;
    int Y;
    int Z;
    BabyCube(int x, int y, int z)
    {
        X = x;
        Y = y;
        Z = z;
        Layers = deque<BabyLayer>();
        for(int i=0;i<z;i++)
        {
            BabyLayer lay = BabyLayer(x,y);
            Layers.push_back(lay);
        }
        NullBaby = Baby();
        NullBaby.setNull(true);
        MakeConnections();
    }
    void MakeConnections()
    {
        int l = Layers.size();
        if(l == 0 || l == 1)
            return;
        for(int layer=0;layer<l;layer++)
        {
            BabyLayer * lay = &Layers[layer];
            if(layer< l-1)
            {
                for(int y=0;y<lay->Height;y++)
                {
                    for(int x=0;x<lay->Width;x++)
                    {
                        //Top Left
                        if(x > 0 && y > 0)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y-1)));
                        //Top Middle
                        if(y > 0)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y-1)));
                        //Top Right
                        if(y > 0 && x+1 < lay->Width-1)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y-1)));
                        //Middle Right
                        if(x+1 < lay->Width -1)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y)));
                        //Bottom Right
                        if(x+1 < lay->Width -1 && y+1 < lay->Height-1)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x+1,y+1)));
                        //Bottom Middle
                        if(y+1 < lay->Height-1)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y+1)));
                        //Bottom Left
                        if(x > 0 && y+1 < lay->Height-1)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y+1)));
                        //Middle Left
                        if(x > 0)
                            Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x-1,y)));
                        //Middle Middle
                        Layers[layer].getBaby(x,y)->addInput(shared_ptr<Baby>(Layers[layer+1].getBaby(x,y)));
                    }

                }
            }
        }
    }
    Baby * getBaby(int x, int y, int z)
    {

        if(z >= Layers.size() || z < 0)
            return &NullBaby;
        if(y >= Layers[z].Height || y < 0)
            return &NullBaby;
        if(x >= Layers[z].Width || x < 0)
            return &NullBaby;

        return Layers[z].getBaby(x,y);
    }
    void Update()
    {

    }
    ~BabyCube(void)
    {

    }
private:
    deque<BabyLayer> Layers;
    Baby NullBaby;
};

Upvotes: 1

Views: 345

Answers (1)

Jeff
Jeff

Reputation: 2193

Out of morbid curiosity, I revisited this question to see if anyone had deciphered it.

The only obvious issue I see with the source code is in BabyLayer::GetBaby():

    Baby n = Baby();
    n.setNull(true);
    if(x >= Width || x <0)
        return &n;             // Bad.
    if(y >= Height || y < 0)
        return &n;             // Bad.

You're declaring a new Baby instance on the stack, then returning a pointer to it. The Baby instance named 'n' gets destructed when GetBaby() returns, and the returned pointer is now invalid.

I don't know what compiler you're using, but Visual Studio 2010 emits, "warning C4172: returning address of local variable or temporary" on these lines. Note that your code sample is incomplete and doesn't actually do anything, I had to declare a BabyCube instance to receive this warning.

Since I can't decipher what your code is supposed to do, and can make no sense of its operation, I can't explain why the memory access exceptions are thrown.

Upvotes: 2

Related Questions