Vector calling destructors when reallocating

2

I have a dynamically allocated 3D array of pointers to class:

class Foo {
public:
    int a;
    float b;
    float c;
    Foo(int x, float y, float z) { a = x; b = y; c = z; }
};

in a class:

class Bar {
public:
    Foo ****p_arr;

    Bar();
    ~Bar();
    void Create();
};

allocated like this (in Bar::Create()):

p_arr = new Foo***[ARR_SIZE];
for (unsigned int i = 0; i < ARR_SIZE; ++i) {
    p_arr[i] = new Foo**[ARR_SIZE];
    for (unsigned int j = 0; j < ARR_SIZE; ++j) {
        p_arr[i][j] = new Foo*[ARR_SIZE];
        for (unsigned int k = 0; k < ARR_SIZE; ++k) {
            if (rand() % (k + 1) < 1)
                p_arr[i][j][k] = new Foo(i, j, k * 0.1f);
            else
                p_arr[i][j][k] = nullptr;
        }
    }
}

And I want to delete it (in ~Bar()):

for (unsigned int i = 0; i < ARR_SIZE; i++) {
    for (unsigned int j = 0; j < ARR_SIZE; j++) {
        for (unsigned int k = 0; k < ARR_SIZE; k++) {
            if (p_arr[i][j][k] != nullptr)
                delete p_arr[i][j][k];
        }
        delete[] p_arr[i][j];
    }
    delete[] p_arr[i];
}
delete[] p_arr;

I have a std::vector of Bars, and when I push_back to the vector new item, the vector is reallocating and calls the destructor. When I am accessing p_arr again, it's deallocated and program crashes in destructor. It says:

0xC0000005: Access violation reading location 0xFFFFFFFF.

It crashes here:

if (p_arr[i][j][k] != nullptr) // <- here
    delete p_arr[i][j][k];

How can I fix it?

c++
arrays
pointers
dynamic
asked on Stack Overflow Apr 29, 2020 by galaxy001 • edited Apr 30, 2020 by galaxy001

2 Answers

1

You can use a 1-dimensional array for storing N-dimensional arrays, as long as N-1 dimensions are of the same fixed size, like yours here. This way it requires only 1 memory allocation, improving memory utilisation and locality and eliminating all the unnecessary complexity.

Example:

#include <memory>

struct Foo {
    int a = 0;
    float b = 0;
    float c = 0;
};

int constexpr ARR_SIZE = 10;

Foo& at(std::unique_ptr<Foo[]> const& a3d, unsigned i, unsigned j, unsigned k) {
    return a3d[(i * ARR_SIZE + j) * ARR_SIZE + k];
}

int main () {
    std::unique_ptr<Foo[]> a3d{new Foo[ARR_SIZE * ARR_SIZE * ARR_SIZE]};
    at(a3d, 0, 0, 0) = {1,2,3};
}

Instead of std::unique_ptr<Foo[]> you can use std::vector<Foo> - the latter is copyable.

answered on Stack Overflow Apr 30, 2020 by Maxim Egorushkin • edited Apr 30, 2020 by Maxim Egorushkin
0

I just added copy constructor to Bar, and code is working fine.

answered on Stack Overflow Apr 30, 2020 by galaxy001

User contributions licensed under CC BY-SA 3.0